diff --git a/pom.xml b/pom.xml
index caba4f1..726fe71 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.tomff.beesplus
BeesPlus
- 1.4.5-SNAPSHOT
+ 1.5
UTF-8
diff --git a/src/main/java/com/tomff/beesplus/BeesPlus.java b/src/main/java/com/tomff/beesplus/BeesPlus.java
index 283e0c5..5d4d514 100644
--- a/src/main/java/com/tomff/beesplus/BeesPlus.java
+++ b/src/main/java/com/tomff/beesplus/BeesPlus.java
@@ -1,15 +1,16 @@
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.gui.GuiViewTracker;
import com.tomff.beesplus.core.items.CustomItemManager;
+import com.tomff.beesplus.core.migrations.AddFields;
+import com.tomff.beesplus.core.migrations.Field;
+import com.tomff.beesplus.core.migrations.MigrationsExecutor;
+import com.tomff.beesplus.handlers.BeehiveHandler;
+import com.tomff.beesplus.handlers.DamageHandler;
+import com.tomff.beesplus.handlers.RightClickHandler;
+import com.tomff.beesplus.items.*;
import com.tomff.beesplus.localization.Localization;
import com.tomff.beesplus.localization.LocalizationWrapper;
import org.bstats.bukkit.Metrics;
@@ -22,63 +23,28 @@ import java.util.Locale;
public class BeesPlus extends JavaPlugin {
- private GuiManager guiManager;
+ private GuiViewTracker guiViewTracker;
private CustomItemManager customItemManager;
- private LocalizationWrapper localizationWrapper;
-
@Override
public void onEnable() {
+ performMigrations();
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();
+ guiViewTracker = new GuiViewTracker();
+ customItemManager = new CustomItemManager(this);
getServer().getPluginManager().registerEvents(new GuiHandler(this), this);
+ getServer().getPluginManager().registerEvents(new BeehiveHandler(), 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);
+ if (!loadLocale()) {
+ getServer().getPluginManager().disablePlugin(this);
+ return;
}
- Metrics metrics = new Metrics(this, 7065);
+ registerItems();
+ setupMetrics();
new UpdateChecker(this, 77224).getVersion(version -> {
if (!this.getDescription().getVersion().equalsIgnoreCase(version)) {
@@ -87,15 +53,91 @@ public class BeesPlus extends JavaPlugin {
});
}
- private void disablePlugin() {
- getServer().getPluginManager().disablePlugin(this);
+ private void setupMetrics() {
+ Metrics metrics = new Metrics(this, 7065);
+
+ metrics.addCustomChart(new Metrics.SimplePie("language_used",
+ () -> getConfig().getString("locale", Locale.ENGLISH.toLanguageTag())));
}
- public GuiManager getGuiManager() {
- return guiManager;
+ @Override
+ public void onDisable() {
+ guiViewTracker.clearViews();
+ }
+
+ private boolean loadLocale() {
+ String locale = getConfig().getString("locale", Locale.ENGLISH.toLanguageTag());
+ LocalizationWrapper 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.");
+
+ return false;
+ } catch (InvalidConfigurationException | IllegalArgumentException e) {
+ getLogger().severe(e.getMessage());
+
+ getLogger().severe("Locale file corrupted or malformed! Please check your locale file.");
+ return false;
+ }
+
+ return true;
+ }
+
+ private void performMigrations() {
+ MigrationsExecutor migrationsExecutor = new MigrationsExecutor(this);
+
+ Field[] beehiveUpgradeTranslation = new Field[] {
+ new Field("beehive_upgrade_item_name", "&6Beehive Upgrade"),
+ new Field("beehive_upgrade_item_lore", "&7Bee capacity: &a+3||&8(Right click to use)"),
+ new Field("beehive_upgrade_success", "&aBeehive upgraded! New population: &7%beesno%&a bees"),
+ new Field("beehive_upgrade_max", "&cError: This beehive has reached the maximum population allowed!")
+ };
+
+ migrationsExecutor.addMigration(1,
+ new AddFields("config.yml", new Field[] {
+ new Field("beehiveupgrade.maximumpopulation", 9)
+ }),
+ new AddFields("locale/en.yml", beehiveUpgradeTranslation),
+ new AddFields("locale/fr.yml", beehiveUpgradeTranslation),
+ new AddFields("locale/hu.yml", beehiveUpgradeTranslation),
+ new AddFields("locale/zh_cn.yml", beehiveUpgradeTranslation),
+ new AddFields("locale/pt.yml", new Field[] {
+ new Field("beehive_upgrade_item_name", "&6Melhorar Colmeia"),
+ new Field("beehive_upgrade_item_lore", "&7População de abelhas: &a+3||&8(Clique direito para usar)"),
+ new Field("beehive_upgrade_success", "&aColmeia melhorada! Nova população: &7%beesno%&a abelhas"),
+ new Field("beehive_upgrade_max", "&cErro: Esta colmeia atingiu a população máxima permitida!")
+ })
+ );
+
+ migrationsExecutor.migrate();
+ }
+
+ private void registerItems() {
+ BeeHiveUpgrade beeHiveUpgrade = new BeeHiveUpgrade(this);
+
+ customItemManager.registerCustomItem("honey_upgrade", beeHiveUpgrade);
+ getServer().getPluginManager().registerEvents(beeHiveUpgrade, this);
+
+ boolean isProtectionSuitEnabled = getConfig().getBoolean("beeprotectionsuit.enabled", true);
+
+ if(isProtectionSuitEnabled) {
+ customItemManager.registerCustomItem("protection_boots", new BeeProtectionBoots());
+ customItemManager.registerCustomItem("protection_leggings", new BeeProtectionLeggings());
+ customItemManager.registerCustomItem("protection_chestplate", new BeeProtectionChestplate());
+ customItemManager.registerCustomItem("protection_helmet", new BeeProtectionHelmet());
+
+ getServer().getPluginManager().registerEvents(new DamageHandler(this), this);
+ }
+ }
+
+ public GuiViewTracker getGuiViewTracker() {
+ return guiViewTracker;
}
public CustomItemManager getCustomItemManager() {
return customItemManager;
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/tomff/beesplus/core/gui/Gui.java b/src/main/java/com/tomff/beesplus/core/gui/Gui.java
index a82d10d..7b56257 100644
--- a/src/main/java/com/tomff/beesplus/core/gui/Gui.java
+++ b/src/main/java/com/tomff/beesplus/core/gui/Gui.java
@@ -30,6 +30,10 @@ public abstract class Gui {
}
}
+ public boolean hasIcon(int slot) {
+ return icons.containsKey(slot);
+ }
+
public Icon getIcon(int slot) {
return icons.get(slot);
}
diff --git a/src/main/java/com/tomff/beesplus/core/gui/GuiHandler.java b/src/main/java/com/tomff/beesplus/core/gui/GuiHandler.java
index 0383d0b..3810835 100644
--- a/src/main/java/com/tomff/beesplus/core/gui/GuiHandler.java
+++ b/src/main/java/com/tomff/beesplus/core/gui/GuiHandler.java
@@ -6,51 +6,76 @@ 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.event.inventory.InventoryCloseEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
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;
+ private final GuiViewTracker guiViewTracker;
public GuiHandler(BeesPlus beesPlus) {
- this.beesPlus = beesPlus;
- this.guiManager = beesPlus.getGuiManager();
+ this.guiViewTracker = beesPlus.getGuiViewTracker();
}
@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
- if (!(event.getWhoClicked() instanceof Player)) {
- return;
- }
+ 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)) {
+ if (!guiViewTracker.isViewingGui(uuid)) {
+ return;
+ }
- event.setCancelled(true);
+ if (guiViewTracker.getView(uuid).getInventoryView() != event.getView()) {
+ return;
+ }
- ItemStack clickedItem = event.getCurrentItem();
+ event.setCancelled(true);
- if (clickedItem == null || clickedItem.getType() == Material.AIR) return;
+ ItemStack clickedItem = event.getCurrentItem();
- Gui gui = guiManager.getOpenedGuis().get(uuid);
+ if (clickedItem == null) return;
+ if (clickedItem.getType() == Material.AIR) return;
- Icon icon = gui.getIcon(event.getRawSlot());
- if (icon == null) return;
+ int slot = event.getRawSlot();
- Consumer callback = icon.getCallback();
- if(callback == null) return;
+ View view = guiViewTracker.getView(uuid);
+ Gui gui = view.getGui();
- icon.getCallback().accept(player);
+ if (!gui.hasIcon(slot)) return;
+
+ Icon icon = gui.getIcon(event.getRawSlot());
+ Consumer callback = icon.getCallback();
+
+ if(callback == null) return;
+
+ icon.getCallback().accept(player);
+ }
+
+ @EventHandler
+ public void onInventoryClose(InventoryCloseEvent event) {
+ if (!(event.getPlayer() instanceof Player)) return;
+
+ Player player = (Player) event.getPlayer();
+ UUID uuid = player.getUniqueId();
+
+ if (!guiViewTracker.isViewingGui(uuid)) {
+ return;
+ }
+
+ if (guiViewTracker.getView(uuid).getInventoryView() == event.getView()) {
+ guiViewTracker.removeView(uuid);
}
}
+ @EventHandler
+ public void onLeave(PlayerQuitEvent event) {
+ guiViewTracker.removeView(event.getPlayer().getUniqueId());
+ }
+
}
diff --git a/src/main/java/com/tomff/beesplus/core/gui/GuiManager.java b/src/main/java/com/tomff/beesplus/core/gui/GuiManager.java
deleted file mode 100644
index 8e74f47..0000000
--- a/src/main/java/com/tomff/beesplus/core/gui/GuiManager.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.tomff.beesplus.core.gui;
-
-import org.bukkit.entity.Player;
-
-import java.util.HashMap;
-import java.util.UUID;
-
-public class GuiManager {
-
- private HashMap 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 getOpenedGuis() {
- return openedGuis;
- }
-}
diff --git a/src/main/java/com/tomff/beesplus/core/gui/GuiViewTracker.java b/src/main/java/com/tomff/beesplus/core/gui/GuiViewTracker.java
new file mode 100644
index 0000000..25c7bfa
--- /dev/null
+++ b/src/main/java/com/tomff/beesplus/core/gui/GuiViewTracker.java
@@ -0,0 +1,39 @@
+package com.tomff.beesplus.core.gui;
+
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryView;
+
+import java.util.HashMap;
+import java.util.UUID;
+
+public class GuiViewTracker {
+
+ private HashMap views;
+
+ public GuiViewTracker() {
+ views = new HashMap<>();
+ }
+
+ public boolean isViewingGui(UUID uuid) {
+ return views.containsKey(uuid);
+ }
+
+ public View getView(UUID uuid) {
+ return views.get(uuid);
+ }
+
+ public void removeView(UUID uuid) {
+ views.remove(uuid);
+ }
+
+ public void clearViews() {
+ views.forEach((uuid, view) -> view.getInventoryView().close());
+ }
+
+ public void openGui(Player player, Gui gui) {
+ gui.buildIcons();
+ InventoryView view = player.openInventory(gui.getInventory());
+
+ views.put(player.getUniqueId(), new View(view, gui));
+ }
+}
diff --git a/src/main/java/com/tomff/beesplus/core/gui/Icon.java b/src/main/java/com/tomff/beesplus/core/gui/Icon.java
index f185336..c3c2a93 100644
--- a/src/main/java/com/tomff/beesplus/core/gui/Icon.java
+++ b/src/main/java/com/tomff/beesplus/core/gui/Icon.java
@@ -15,7 +15,7 @@ public class Icon {
this.callback = callback;
}
- public Consumer getCallback() {
+ public Consumer getCallback() {
return callback;
}
diff --git a/src/main/java/com/tomff/beesplus/core/gui/View.java b/src/main/java/com/tomff/beesplus/core/gui/View.java
new file mode 100644
index 0000000..6bf8ae7
--- /dev/null
+++ b/src/main/java/com/tomff/beesplus/core/gui/View.java
@@ -0,0 +1,22 @@
+package com.tomff.beesplus.core.gui;
+
+import org.bukkit.inventory.InventoryView;
+
+public class View {
+
+ private final InventoryView inventoryView;
+ private final Gui gui;
+
+ public View(InventoryView inventoryView, Gui gui) {
+ this.inventoryView = inventoryView;
+ this.gui = gui;
+ }
+
+ public InventoryView getInventoryView() {
+ return inventoryView;
+ }
+
+ public Gui getGui() {
+ return gui;
+ }
+}
diff --git a/src/main/java/com/tomff/beesplus/core/items/CustomItem.java b/src/main/java/com/tomff/beesplus/core/items/CustomItem.java
index f1eebf4..dbb04e2 100644
--- a/src/main/java/com/tomff/beesplus/core/items/CustomItem.java
+++ b/src/main/java/com/tomff/beesplus/core/items/CustomItem.java
@@ -9,13 +9,6 @@ public abstract class CustomItem {
public abstract String[] getRecipe();
public abstract Map getIngredients();
- public abstract String getName();
- public abstract Material getMaterial();
-
- public ItemStack getItem() {
- return new ItemBuilder(getMaterial())
- .setName(getName())
- .build();
- }
+ public abstract ItemStack getResult();
}
diff --git a/src/main/java/com/tomff/beesplus/core/items/CustomItemManager.java b/src/main/java/com/tomff/beesplus/core/items/CustomItemManager.java
index 6b33370..d1a8bec 100644
--- a/src/main/java/com/tomff/beesplus/core/items/CustomItemManager.java
+++ b/src/main/java/com/tomff/beesplus/core/items/CustomItemManager.java
@@ -24,16 +24,12 @@ public class CustomItemManager {
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);
+ NamespacedKey namespacedKey = new NamespacedKey(beesPlus, id);
+ ShapedRecipe recipe = new ShapedRecipe(namespacedKey, customItem.getResult());
+ recipe.shape(customItem.getRecipe());
+ customItem.getIngredients().forEach(recipe::setIngredient);
- Bukkit.addRecipe(recipe);
- });
+ Bukkit.addRecipe(recipe);
}
}
diff --git a/src/main/java/com/tomff/beesplus/core/items/ItemBuilder.java b/src/main/java/com/tomff/beesplus/core/items/ItemBuilder.java
index 2896e29..a6fbfe3 100644
--- a/src/main/java/com/tomff/beesplus/core/items/ItemBuilder.java
+++ b/src/main/java/com/tomff/beesplus/core/items/ItemBuilder.java
@@ -1,8 +1,12 @@
package com.tomff.beesplus.core.items;
import org.bukkit.Material;
+import org.bukkit.NamespacedKey;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.persistence.PersistentDataType;
import java.util.Arrays;
@@ -33,6 +37,30 @@ public class ItemBuilder {
return this;
}
+ public ItemBuilder enchant(Enchantment enchantment, int level) {
+ item.addUnsafeEnchantment(enchantment, level);
+
+ return this;
+ }
+
+ public ItemBuilder hideEnchantments() {
+ ItemMeta meta = item.getItemMeta();
+ meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
+
+ item.setItemMeta(meta);
+
+ return this;
+ }
+
+ public ItemBuilder setPersistentData(NamespacedKey key, PersistentDataType type, Z value) {
+ ItemMeta meta = item.getItemMeta();
+ meta.getPersistentDataContainer().set(key, type, value);
+
+ item.setItemMeta(meta);
+
+ return this;
+ }
+
public ItemStack build() {
return item;
}
diff --git a/src/main/java/com/tomff/beesplus/core/migrations/AddFields.java b/src/main/java/com/tomff/beesplus/core/migrations/AddFields.java
new file mode 100644
index 0000000..d3ba35a
--- /dev/null
+++ b/src/main/java/com/tomff/beesplus/core/migrations/AddFields.java
@@ -0,0 +1,38 @@
+package com.tomff.beesplus.core.migrations;
+
+import org.bukkit.configuration.InvalidConfigurationException;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+import java.io.File;
+import java.io.IOException;
+
+public class AddFields implements Operation {
+ private File file;
+ private Field[] fields;
+
+ public AddFields(String filePath, Field[] fields) {
+ file = new File(BASE_PATH, filePath);
+ this.fields = fields;
+ }
+
+ @Override
+ public void execute() throws IOException {
+ if (!file.exists()) {
+ return;
+ }
+
+ YamlConfiguration config = new YamlConfiguration();
+
+ try {
+ config.load(file);
+ } catch (IOException | InvalidConfigurationException e) {
+ e.printStackTrace();
+ }
+
+ for (Field field : fields) {
+ config.set(field.getPath(), field.getValue());
+ }
+
+ config.save(file);
+ }
+}
diff --git a/src/main/java/com/tomff/beesplus/core/migrations/Field.java b/src/main/java/com/tomff/beesplus/core/migrations/Field.java
new file mode 100644
index 0000000..8305396
--- /dev/null
+++ b/src/main/java/com/tomff/beesplus/core/migrations/Field.java
@@ -0,0 +1,19 @@
+package com.tomff.beesplus.core.migrations;
+
+public class Field {
+ private final String path;
+ private final Object value;
+
+ public Field(String path, Object value) {
+ this.path = path;
+ this.value = value;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/com/tomff/beesplus/core/migrations/MigrationsExecutor.java b/src/main/java/com/tomff/beesplus/core/migrations/MigrationsExecutor.java
new file mode 100644
index 0000000..b4c9209
--- /dev/null
+++ b/src/main/java/com/tomff/beesplus/core/migrations/MigrationsExecutor.java
@@ -0,0 +1,122 @@
+package com.tomff.beesplus.core.migrations;
+
+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.util.HashMap;
+import java.util.Map;
+
+public class MigrationsExecutor {
+ private int latestVersion;
+
+ private Map migrations;
+ private File migrationFileRegistry;
+ private YamlConfiguration yaml;
+
+ private BeesPlus beesPlus;
+
+ public MigrationsExecutor(BeesPlus beesPlus) {
+ this.beesPlus = beesPlus;
+ this.migrations = new HashMap<>();
+ this.yaml = new YamlConfiguration();
+ this.migrationFileRegistry = new File(beesPlus.getDataFolder(), "migration.yml");
+ this.latestVersion = 0;
+ }
+
+ public void addMigration(int version, Operation... operations) {
+ migrations.put(version, operations);
+
+ if (version > latestVersion) {
+ this.latestVersion = version;
+ }
+ }
+
+ public void migrate() {
+ if (hasConfig() && !hasMigrationRegistry()) {
+ loadRegistry();
+
+ migrateFrom(0);
+ return;
+ }
+
+ if (!loadRegistry()) return;
+
+ int version = yaml.getInt("migration", 0);
+ if (version == latestVersion) return;
+
+ migrateFrom(version);
+ }
+
+ private void migrateFrom(int version) {
+ beesPlus.getLogger().info("Old files detected. Migrating files to migration v" + latestVersion);
+
+ for (int nextVersion = version + 1; nextVersion <= latestVersion; nextVersion++) {
+ performMigration(migrations.get(nextVersion));
+ }
+
+ setCurrentMigration(latestVersion);
+ }
+
+ public void setCurrentMigration(int version) {
+ yaml.set("migration", version);
+
+ try {
+ yaml.save(migrationFileRegistry);
+ } catch (IOException e) {
+ beesPlus.getLogger().severe("An error occurred while trying to update the migration version");
+ e.printStackTrace();
+ }
+ }
+
+ private void createIfNotExist() {
+ if (!hasMigrationRegistry()) {
+ yaml.set("migration", latestVersion);
+
+ try {
+ yaml.save(migrationFileRegistry);
+ } catch (IOException e) {
+ e.printStackTrace();
+ beesPlus.getLogger().severe("An error occurred while trying to create the migration registry file!");
+ }
+ }
+ }
+
+ private boolean loadRegistry() {
+ createIfNotExist();
+
+ try {
+ yaml.load(migrationFileRegistry);
+ } catch (IOException | InvalidConfigurationException e) {
+ beesPlus.getLogger().severe("An error occurred while opening the migration registry file.");
+ beesPlus.getLogger().severe("Suggested action: please delete the BeesPlus plugin folder and restart.");
+ e.printStackTrace();
+
+ return false;
+ }
+
+ return true;
+ }
+
+ private void performMigration(Operation[] operations) {
+ for(Operation operation : operations) {
+ try {
+ operation.execute();
+ } catch (IOException e) {
+ e.printStackTrace();
+ beesPlus.getLogger().severe("An error occurred while migrating a file");
+ }
+ }
+ }
+
+ private boolean hasMigrationRegistry() {
+ return migrationFileRegistry.exists();
+ }
+
+ private boolean hasConfig() {
+ return new File(beesPlus.getDataFolder(), "config.yml").exists();
+ }
+
+}
diff --git a/src/main/java/com/tomff/beesplus/core/migrations/Operation.java b/src/main/java/com/tomff/beesplus/core/migrations/Operation.java
new file mode 100644
index 0000000..3976688
--- /dev/null
+++ b/src/main/java/com/tomff/beesplus/core/migrations/Operation.java
@@ -0,0 +1,13 @@
+package com.tomff.beesplus.core.migrations;
+
+import com.tomff.beesplus.BeesPlus;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.io.File;
+import java.io.IOException;
+
+public interface Operation {
+ File BASE_PATH = JavaPlugin.getPlugin(BeesPlus.class).getDataFolder();
+
+ void execute() throws IOException;
+}
diff --git a/src/main/java/com/tomff/beesplus/gui/BeeHiveInfo.java b/src/main/java/com/tomff/beesplus/gui/BeeHiveInfo.java
index ff1dfb9..dcf915e 100644
--- a/src/main/java/com/tomff/beesplus/gui/BeeHiveInfo.java
+++ b/src/main/java/com/tomff/beesplus/gui/BeeHiveInfo.java
@@ -8,8 +8,6 @@ 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.inventory.ItemStack;
public class BeeHiveInfo extends Gui {
@@ -54,26 +52,6 @@ public class BeeHiveInfo extends Gui {
}
}
- 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) {
- return beehive.getEntityCount();
- }
-
- private int getBeehiveMaxPopulation(Beehive beehive) {
- return beehive.getMaxEntities();
- }
-
@Override
public void buildIcons() {
org.bukkit.block.data.type.Beehive beehiveData = (org.bukkit.block.data.type.Beehive) beehive.getBlockData();
@@ -87,12 +65,12 @@ public class BeeHiveInfo extends Gui {
Icon honeyLevelIcon = new Icon(honeyLevel, null);
setIcon(honeyLevelIcon, 10);
- String isSedated = isSedated(beehive.getLocation()) ? Localization.get(Localization.BEEHIVE_INFO_GUI_SEDATED) :
+ String isSedated = beehive.isSedated() ? 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)),
+ .setLore(Localization.get(Localization.BEEHIVE_INFO_GUI_BEE_CAPACITY_DESC, beehive.getEntityCount(), beehive.getMaxEntities()),
isSedated)
.build();
@@ -114,7 +92,8 @@ public class BeeHiveInfo extends Gui {
Icon flowerIcon = new Icon(flower, null);
setIcon(flowerIcon, 37);
- HoneyLevelIndicators honeyLevelIndicator = HoneyLevelIndicators.getFromLevel(beehiveData.getHoneyLevel());
+ HoneyLevelIndicators honeyLevelIndicator = HoneyLevelIndicators.getFromLevel(beehiveData.getHoneyLevel(),
+ beehiveData.getMaximumHoneyLevel());
setHoneyLevelSlots(honeyLevelIndicator);
ItemStack filler = new ItemBuilder(Material.WHITE_STAINED_GLASS_PANE)
diff --git a/src/main/java/com/tomff/beesplus/gui/HoneyLevelIndicators.java b/src/main/java/com/tomff/beesplus/gui/HoneyLevelIndicators.java
index a221d48..c5edd05 100644
--- a/src/main/java/com/tomff/beesplus/gui/HoneyLevelIndicators.java
+++ b/src/main/java/com/tomff/beesplus/gui/HoneyLevelIndicators.java
@@ -4,8 +4,6 @@ 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),
@@ -28,15 +26,16 @@ public enum HoneyLevelIndicators {
this.slots = slots;
}
- public static HoneyLevelIndicators getFromLevel(int level) {
- return Arrays.stream(values())
- .filter((levelIndicator) -> levelIndicator.level == level)
- .findFirst()
- .orElse(VERY_HIGH);
- }
+ public static HoneyLevelIndicators getFromLevel(int currentHoneyLvl, int maxHoneyLvl) {
+ float ratio = (float) currentHoneyLvl / (float) maxHoneyLvl;
- public int getLevel() {
- return level;
+ if (ratio == 0) return EMPTY;
+ if (ratio <= 0.25) return LOW;
+ if (ratio <= 0.50) return MEDIUM;
+ if (ratio <= 0.75) return HIGH;
+ if (ratio <= 1) return VERY_HIGH;
+
+ return EMPTY;
}
public ChatColor getColor() {
diff --git a/src/main/java/com/tomff/beesplus/handlers/BeehiveHandler.java b/src/main/java/com/tomff/beesplus/handlers/BeehiveHandler.java
new file mode 100644
index 0000000..58aaec1
--- /dev/null
+++ b/src/main/java/com/tomff/beesplus/handlers/BeehiveHandler.java
@@ -0,0 +1,48 @@
+package com.tomff.beesplus.handlers;
+
+import org.bukkit.Material;
+import org.bukkit.block.BlockState;
+import org.bukkit.entity.Item;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.BlockDropItemEvent;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.BlockStateMeta;
+
+public class BeehiveHandler implements Listener {
+
+ @EventHandler
+ public void onBeeHiveBreak(BlockDropItemEvent event) {
+ BlockState blockState = event.getBlockState();
+ Material blockType = blockState.getType();
+
+ if (blockType != Material.BEEHIVE) {
+ return;
+ }
+
+ if (event.getItems().size() == 0) {
+ return;
+ }
+
+ event.getItems()
+ .stream()
+ .filter(this::validBeehive)
+ .findFirst()
+ .ifPresent(item -> saveState(blockState, item));
+ }
+
+ private boolean validBeehive(Item item) {
+ ItemStack itemStack = item.getItemStack();
+
+ return (!itemStack.hasItemMeta() && itemStack.getType() == Material.BEEHIVE);
+ }
+
+ private void saveState(BlockState state, Item item) {
+ ItemStack itemStack = item.getItemStack();
+ BlockStateMeta itemMeta = (BlockStateMeta) itemStack.getItemMeta();
+
+ itemMeta.setBlockState(state);
+ itemStack.setItemMeta(itemMeta);
+ item.setItemStack(itemStack);
+ }
+}
diff --git a/src/main/java/com/tomff/beesplus/handlers/DamageHandler.java b/src/main/java/com/tomff/beesplus/handlers/DamageHandler.java
index f8f9995..6be39b9 100644
--- a/src/main/java/com/tomff/beesplus/handlers/DamageHandler.java
+++ b/src/main/java/com/tomff/beesplus/handlers/DamageHandler.java
@@ -41,14 +41,16 @@ public class DamageHandler implements Listener {
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())) {
+ if (!Stream.of(playerInventory.getArmorContents()).allMatch(Objects::nonNull)) {
+ return;
+ }
- event.setDamage(reduction * event.getDamage());
- }
+ if (playerInventory.getHelmet().isSimilar(helmet.getResult()) &&
+ playerInventory.getChestplate().isSimilar(chestplate.getResult()) &&
+ playerInventory.getLeggings().isSimilar(leggings.getResult()) &&
+ playerInventory.getBoots().isSimilar(boots.getResult())) {
+
+ event.setDamage(reduction * event.getDamage());
}
}
}
diff --git a/src/main/java/com/tomff/beesplus/handlers/RightClickHandler.java b/src/main/java/com/tomff/beesplus/handlers/RightClickHandler.java
index 8dc109f..6db8506 100644
--- a/src/main/java/com/tomff/beesplus/handlers/RightClickHandler.java
+++ b/src/main/java/com/tomff/beesplus/handlers/RightClickHandler.java
@@ -3,7 +3,7 @@ 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 com.tomff.beesplus.core.gui.GuiViewTracker;
import org.bukkit.EntityEffect;
import org.bukkit.Material;
import org.bukkit.block.Beehive;
@@ -24,7 +24,7 @@ import java.util.Arrays;
public class RightClickHandler implements Listener {
private final BeesPlus beesPlus;
- private final GuiManager guiManager;
+ private final GuiViewTracker guiViewTracker;
private final boolean removeAnger;
@@ -40,7 +40,7 @@ public class RightClickHandler implements Listener {
public RightClickHandler(BeesPlus beesPlus) {
this.beesPlus = beesPlus;
- this.guiManager = beesPlus.getGuiManager();
+ this.guiViewTracker = beesPlus.getGuiViewTracker();
removeAnger = beesPlus.getConfig().getBoolean("healing.removeanger", true);
}
@@ -64,7 +64,7 @@ public class RightClickHandler implements Listener {
if (player.isSneaking() && player.hasPermission("beesplus.bee.view")) {
event.setCancelled(true);
- guiManager.openGui(player, new BeeInfo(bee));
+ guiViewTracker.openGui(player, new BeeInfo(bee));
return;
}
@@ -99,7 +99,7 @@ public class RightClickHandler implements Listener {
event.setCancelled(true);
Beehive beehive = (Beehive) clickedBlock.getState();
- guiManager.openGui(player, new BeeHiveInfo(beehive));
+ guiViewTracker.openGui(player, new BeeHiveInfo(beehive));
}
}
}
diff --git a/src/main/java/com/tomff/beesplus/items/BeeHiveUpgrade.java b/src/main/java/com/tomff/beesplus/items/BeeHiveUpgrade.java
new file mode 100644
index 0000000..224bcae
--- /dev/null
+++ b/src/main/java/com/tomff/beesplus/items/BeeHiveUpgrade.java
@@ -0,0 +1,130 @@
+package com.tomff.beesplus.items;
+
+import com.tomff.beesplus.BeesPlus;
+import com.tomff.beesplus.core.items.CustomItem;
+import com.tomff.beesplus.core.items.ItemBuilder;
+import com.tomff.beesplus.localization.Localization;
+import org.bukkit.Material;
+import org.bukkit.NamespacedKey;
+import org.bukkit.Sound;
+import org.bukkit.block.Beehive;
+import org.bukkit.block.Block;
+import org.bukkit.enchantments.Enchantment;
+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.PlayerInteractEvent;
+import org.bukkit.inventory.EquipmentSlot;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.persistence.PersistentDataContainer;
+import org.bukkit.persistence.PersistentDataType;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class BeeHiveUpgrade extends CustomItem implements Listener {
+
+ private NamespacedKey upgradeKey;
+ private int maxPopulation;
+
+ public BeeHiveUpgrade(BeesPlus beesPlus) {
+ upgradeKey = new NamespacedKey(beesPlus, "upgrade");
+ maxPopulation = beesPlus.getConfig().getInt("beehiveupgrade.maximumpopulation", 9);
+ }
+
+ @Override
+ public String[] getRecipe() {
+ return new String[] {
+ "CCC",
+ "CHC",
+ "CCC"
+ };
+ }
+
+ @Override
+ public Map getIngredients() {
+ Map ingredients = new HashMap<>();
+
+ ingredients.put('C', Material.HONEYCOMB);
+ ingredients.put('H', Material.BEEHIVE);
+
+ return ingredients;
+ }
+
+ @Override
+ public ItemStack getResult() {
+ return new ItemBuilder(Material.HONEYCOMB)
+ .setName(Localization.get(Localization.BEEHIVE_UPGRADE_ITEM_NAME))
+ .setLore(Localization.get(Localization.BEEHIVE_UPGRADE_ITEM_LORE).split("\\|\\|"))
+ .setPersistentData(upgradeKey, PersistentDataType.STRING, "beehive")
+ .enchant(Enchantment.DURABILITY, 1)
+ .hideEnchantments()
+ .build();
+ }
+
+ @EventHandler
+ public void onHiveClick(PlayerInteractEvent event) {
+ Player player = event.getPlayer();
+ Action action = event.getAction();
+ Block clickedBlock = event.getClickedBlock();
+
+ if (event.getHand() != EquipmentSlot.HAND) {
+ return;
+ }
+
+ if (clickedBlock == null) {
+ return;
+ }
+
+ if (event.getItem() == null) {
+ return;
+ }
+
+ if (action == Action.RIGHT_CLICK_BLOCK && clickedBlock.getType().equals(Material.BEEHIVE)) {
+ ItemStack handItem = event.getItem();
+ ItemMeta handItemMeta = handItem.getItemMeta();
+
+ if (handItemMeta == null) {
+ return;
+ }
+
+ PersistentDataContainer container = handItemMeta.getPersistentDataContainer();
+
+ if (!container.has(upgradeKey, PersistentDataType.STRING)) {
+ return;
+ }
+
+ String upgradeType = container.get(upgradeKey, PersistentDataType.STRING);
+
+ if (upgradeType.equals("beehive")) {
+ event.setCancelled(true);
+
+ Beehive beehive = (Beehive) clickedBlock.getState();
+
+ if (!player.hasPermission("beesplus.beehive.upgrade")) {
+ return;
+ }
+
+ if (beehive.getMaxEntities() >= maxPopulation) {
+ Localization.sendMessage(player, Localization.BEEHIVE_UPGRADE_MAX);
+ player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 2, 2);
+
+ return;
+ }
+
+ beehive.setMaxEntities(beehive.getMaxEntities() + 3);
+ beehive.update();
+
+ Localization.sendMessage(player, Localization.BEEHIVE_UPGRADE_SUCCESS, beehive.getMaxEntities());
+ player.playSound(player.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 2, 2);
+
+ ItemStack upgradeAmountRemove = handItem.clone();
+ upgradeAmountRemove.setAmount(1);
+
+ player.getInventory().removeItem(upgradeAmountRemove);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/tomff/beesplus/items/BeeProtectionBoots.java b/src/main/java/com/tomff/beesplus/items/BeeProtectionBoots.java
index 8d9fb92..e77af44 100644
--- a/src/main/java/com/tomff/beesplus/items/BeeProtectionBoots.java
+++ b/src/main/java/com/tomff/beesplus/items/BeeProtectionBoots.java
@@ -1,8 +1,10 @@
package com.tomff.beesplus.items;
import com.tomff.beesplus.core.items.CustomItem;
+import com.tomff.beesplus.core.items.ItemBuilder;
import com.tomff.beesplus.localization.Localization;
import org.bukkit.Material;
+import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.Map;
@@ -28,12 +30,9 @@ public class BeeProtectionBoots extends CustomItem {
}
@Override
- public String getName() {
- return Localization.get(Localization.BEE_PROTECTION_BOOTS);
- }
-
- @Override
- public Material getMaterial() {
- return Material.CHAINMAIL_BOOTS;
+ public ItemStack getResult() {
+ return new ItemBuilder(Material.CHAINMAIL_BOOTS)
+ .setName(Localization.get(Localization.BEE_PROTECTION_BOOTS))
+ .build();
}
}
diff --git a/src/main/java/com/tomff/beesplus/items/BeeProtectionChestplate.java b/src/main/java/com/tomff/beesplus/items/BeeProtectionChestplate.java
index dfa106d..b88b90c 100644
--- a/src/main/java/com/tomff/beesplus/items/BeeProtectionChestplate.java
+++ b/src/main/java/com/tomff/beesplus/items/BeeProtectionChestplate.java
@@ -1,8 +1,10 @@
package com.tomff.beesplus.items;
import com.tomff.beesplus.core.items.CustomItem;
+import com.tomff.beesplus.core.items.ItemBuilder;
import com.tomff.beesplus.localization.Localization;
import org.bukkit.Material;
+import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.Map;
@@ -28,12 +30,9 @@ public class BeeProtectionChestplate extends CustomItem {
}
@Override
- public String getName() {
- return Localization.get(Localization.BEE_PROTECTION_CHESTPLATE);
- }
-
- @Override
- public Material getMaterial() {
- return Material.CHAINMAIL_CHESTPLATE;
+ public ItemStack getResult() {
+ return new ItemBuilder(Material.CHAINMAIL_CHESTPLATE)
+ .setName(Localization.get(Localization.BEE_PROTECTION_CHESTPLATE))
+ .build();
}
}
diff --git a/src/main/java/com/tomff/beesplus/items/BeeProtectionHelmet.java b/src/main/java/com/tomff/beesplus/items/BeeProtectionHelmet.java
index cd33229..9d1f446 100644
--- a/src/main/java/com/tomff/beesplus/items/BeeProtectionHelmet.java
+++ b/src/main/java/com/tomff/beesplus/items/BeeProtectionHelmet.java
@@ -1,8 +1,10 @@
package com.tomff.beesplus.items;
import com.tomff.beesplus.core.items.CustomItem;
+import com.tomff.beesplus.core.items.ItemBuilder;
import com.tomff.beesplus.localization.Localization;
import org.bukkit.Material;
+import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.Map;
@@ -28,12 +30,9 @@ public class BeeProtectionHelmet extends CustomItem {
}
@Override
- public String getName() {
- return Localization.get(Localization.BEE_PROTECTION_HELMET);
- }
-
- @Override
- public Material getMaterial() {
- return Material.CHAINMAIL_HELMET;
+ public ItemStack getResult() {
+ return new ItemBuilder(Material.CHAINMAIL_HELMET)
+ .setName(Localization.get(Localization.BEE_PROTECTION_HELMET))
+ .build();
}
}
diff --git a/src/main/java/com/tomff/beesplus/items/BeeProtectionLeggings.java b/src/main/java/com/tomff/beesplus/items/BeeProtectionLeggings.java
index 897d44d..dc5d439 100644
--- a/src/main/java/com/tomff/beesplus/items/BeeProtectionLeggings.java
+++ b/src/main/java/com/tomff/beesplus/items/BeeProtectionLeggings.java
@@ -1,8 +1,10 @@
package com.tomff.beesplus.items;
import com.tomff.beesplus.core.items.CustomItem;
+import com.tomff.beesplus.core.items.ItemBuilder;
import com.tomff.beesplus.localization.Localization;
import org.bukkit.Material;
+import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.Map;
@@ -28,12 +30,9 @@ public class BeeProtectionLeggings extends CustomItem {
}
@Override
- public String getName() {
- return Localization.get(Localization.BEE_PROTECTION_LEGGINGS);
- }
-
- @Override
- public Material getMaterial() {
- return Material.CHAINMAIL_LEGGINGS;
+ public ItemStack getResult() {
+ return new ItemBuilder(Material.CHAINMAIL_LEGGINGS)
+ .setName(Localization.get(Localization.BEE_PROTECTION_LEGGINGS))
+ .build();
}
}
diff --git a/src/main/java/com/tomff/beesplus/localization/Localization.java b/src/main/java/com/tomff/beesplus/localization/Localization.java
index 629151c..f6a4142 100644
--- a/src/main/java/com/tomff/beesplus/localization/Localization.java
+++ b/src/main/java/com/tomff/beesplus/localization/Localization.java
@@ -43,6 +43,10 @@ public enum Localization {
BEE_PROTECTION_CHESTPLATE,
BEE_PROTECTION_LEGGINGS,
BEE_PROTECTION_BOOTS,
+ BEEHIVE_UPGRADE_ITEM_NAME,
+ BEEHIVE_UPGRADE_ITEM_LORE,
+ BEEHIVE_UPGRADE_SUCCESS("beesno"),
+ BEEHIVE_UPGRADE_MAX,
HONEY_LOW,
HONEY_MEDIUM,
HONEY_HIGH,
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index e6dd67c..bea81be 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -23,4 +23,11 @@ beeprotectionsuit:
# removeanger: remove anger from bees when they are healed?
#
healing:
- removeanger: true
\ No newline at end of file
+ removeanger: true
+
+# Beehive upgrade settings
+#
+# maximumSize: maximum number of bees a beehive can be upgraded to
+#
+beehiveupgrade:
+ maximumpopulation: 9
\ No newline at end of file
diff --git a/src/main/resources/locale/en.yml b/src/main/resources/locale/en.yml
index c6c9151..49eb2ff 100644
--- a/src/main/resources/locale/en.yml
+++ b/src/main/resources/locale/en.yml
@@ -76,4 +76,15 @@ ride_bee_subtitle: "&6a bee &8%name%&6!"
bee_protection_helmet: "&6Bee Protection Helmet"
bee_protection_chestplate: "&6Bee Protection Chestplate"
bee_protection_leggings: "&6Bee Protection Leggings"
-bee_protection_boots: "&6Bee Protection Boots"
\ No newline at end of file
+bee_protection_boots: "&6Bee Protection Boots"
+
+###################
+# Beehive upgrade item
+###################
+beehive_upgrade_item_name: "&6Beehive Upgrade"
+
+# Use || to a create a new line
+beehive_upgrade_item_lore: "&7Bee capacity: &a+3||&8(Right click to use)"
+
+beehive_upgrade_success: "&aBeehive upgraded! New population: &7%beesno%&a bees"
+beehive_upgrade_max: "&cError: This beehive has reached the maximum population allowed!"
\ No newline at end of file
diff --git a/src/main/resources/locale/fr.yml b/src/main/resources/locale/fr.yml
index 8ecfd16..44894ba 100644
--- a/src/main/resources/locale/fr.yml
+++ b/src/main/resources/locale/fr.yml
@@ -82,4 +82,15 @@ ride_bee_subtitle: "&6a abeille &8%name%&6!"
bee_protection_helmet: "&6Casque de Protection des Abeilles"
bee_protection_chestplate: "&6Plastron de Protection des Abeilles"
bee_protection_leggings: "&6Leggings de Protection des Abeilles"
-bee_protection_boots: "&6Bottes de protection des abeilles"
\ No newline at end of file
+bee_protection_boots: "&6Bottes de protection des abeilles"
+
+###################
+# Beehive upgrade item
+###################
+beehive_upgrade_item_name: "&6Beehive Upgrade"
+
+# Use || to a create a new line
+beehive_upgrade_item_lore: "&7Bee capacity: &a+3||&8(Right click to use)"
+
+beehive_upgrade_success: "&aBeehive upgraded! New population: &7%beesno%&a bees"
+beehive_upgrade_max: "&cError: This beehive has reached the maximum population allowed!"
\ No newline at end of file
diff --git a/src/main/resources/locale/hu.yml b/src/main/resources/locale/hu.yml
index d1e5f07..ab93893 100644
--- a/src/main/resources/locale/hu.yml
+++ b/src/main/resources/locale/hu.yml
@@ -82,4 +82,15 @@ ride_bee_subtitle: "&6méhecskén &8%name%&6!"
bee_protection_helmet: "&6Méh Védelmi Sisak"
bee_protection_chestplate: "&6Méh Védelmi Mellvért"
bee_protection_leggings: "&6Méh Védelmi Lábszárvédő"
-bee_protection_boots: "&6Méh Védelmi Csizma"
\ No newline at end of file
+bee_protection_boots: "&6Méh Védelmi Csizma"
+
+###################
+# Méhkas fejlesztő eszköz
+###################
+beehive_upgrade_item_name: "&6Méhkas fejlesztés"
+
+# Használd a || jelzést, hogy elkészíts egy új sort.
+beehive_upgrade_item_lore: "&7Méh kapacitás: &a+3||&8(Jobb klikk, hogy használd)"
+
+beehive_upgrade_success: "&aMéhkas felfejlesztve! Új populáció: &7%beesno%&a méh"
+beehive_upgrade_max: "&cHiba: Ez a méhkas elérte a megengedett maximum populációt!"
\ No newline at end of file
diff --git a/src/main/resources/locale/pt.yml b/src/main/resources/locale/pt.yml
index 6f9e770..ce32c4e 100644
--- a/src/main/resources/locale/pt.yml
+++ b/src/main/resources/locale/pt.yml
@@ -76,4 +76,15 @@ ride_bee_subtitle: "&6uma abelha &8%name%&6!"
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"
\ No newline at end of file
+bee_protection_boots: "&6Proteção contra abelhas"
+
+###################
+# Beehive upgrade item
+###################
+beehive_upgrade_item_name: "&6Melhorar Colmeia"
+
+# Use || to a create a new line
+beehive_upgrade_item_lore: "&7População de abelhas: &a+3||&8(Clique direito para usar)"
+
+beehive_upgrade_success: "&aColmeia melhorada! Nova população: &7%beesno%&a abelhas"
+beehive_upgrade_max: "&cErro: Esta colmeia atingiu a população máxima permitida!"
\ No newline at end of file
diff --git a/src/main/resources/locale/zh_cn.yml b/src/main/resources/locale/zh_cn.yml
index 3665a2d..8d54194 100644
--- a/src/main/resources/locale/zh_cn.yml
+++ b/src/main/resources/locale/zh_cn.yml
@@ -82,4 +82,15 @@ ride_bee_subtitle: "&6一只蜜蜂 &8%name%&6!"
bee_protection_helmet: "&6防蜂头盔"
bee_protection_chestplate: "&6蜜蜂保护胸甲"
bee_protection_leggings: "&6蜜蜂护腿"
-bee_protection_boots: "&6蜜蜂保护靴"
\ No newline at end of file
+bee_protection_boots: "&6蜜蜂保护靴"
+
+###################
+# Beehive upgrade item
+###################
+beehive_upgrade_item_name: "&6Beehive Upgrade"
+
+# Use || to a create a new line
+beehive_upgrade_item_lore: "&7Bee capacity: &a+3||&8(Right click to use)"
+
+beehive_upgrade_success: "&aBeehive upgraded! New population: &7%beesno%&a bees"
+beehive_upgrade_max: "&cError: This beehive has reached the maximum population allowed!"
\ No newline at end of file
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index df53186..1df202f 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -12,4 +12,6 @@ permissions:
default: op
beesplus.beehive.view:
default: op
+ beesplus.beehive.upgrade:
+ default: op