diff --git a/pom.xml b/pom.xml
index 3f6b262a..71221d29 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
net.jeqo
bloons
- 2.1.0
+ 2.1.1
jar
Bloons
diff --git a/src/main/java/net/jeqo/bloons/Bloons.java b/src/main/java/net/jeqo/bloons/Bloons.java
index 60766065..17a47276 100644
--- a/src/main/java/net/jeqo/bloons/Bloons.java
+++ b/src/main/java/net/jeqo/bloons/Bloons.java
@@ -6,6 +6,7 @@
import net.jeqo.bloons.balloon.multipart.balloon.MultipartBalloon;
import net.jeqo.bloons.balloon.single.SingleBalloon;
import net.jeqo.bloons.commands.manager.CommandCore;
+import net.jeqo.bloons.configuration.PluginConfiguration;
import net.jeqo.bloons.listeners.*;
import net.jeqo.bloons.listeners.multipart.MultipartBalloonPlayerJoinListener;
import net.jeqo.bloons.listeners.multipart.MultipartBalloonPlayerLeaveListener;
@@ -14,6 +15,7 @@
import net.jeqo.bloons.health.UpdateChecker;
import net.jeqo.bloons.logger.Logger;
import net.jeqo.bloons.health.Metrics;
+import net.jeqo.bloons.utils.VersionChecker;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.HashMap;
@@ -77,9 +79,9 @@ public void onEnable() {
// Stage listeners
getListenerCore().stageListener(new SingleBalloonPlayerListener());
- getListenerCore().stageListener(new BalloonUnleashListener());
+ getListenerCore().stageListener(new BalloonChickenLeashListener());
getListenerCore().stageListener(new BalloonMenuListener());
- getListenerCore().stageListener(new BalloonEntityListener());
+ getListenerCore().stageListener(new BalloonChickenEntityListener());
getListenerCore().stageListener(new MultipartBalloonPlayerJoinListener());
getListenerCore().stageListener(new MultipartBalloonPlayerLeaveListener());
@@ -88,9 +90,7 @@ public void onEnable() {
getListenerCore().registerListeners();
// Startup the metrics and update checker
- // This is the ID of the plugin on bStats, this should be kept as a constant
- int pluginId = 16872;
- new Metrics(this, pluginId);
+ new Metrics(this, PluginConfiguration.BSTATS_PLUGIN_ID);
updateChecker();
// Copy over example balloons folder
@@ -143,41 +143,11 @@ public void updateChecker() {
new UpdateChecker(this, resourceId).getVersion(version -> {
String currentVersion = this.getDescription().getVersion();
- if (isVersionLower(currentVersion, version)) {
+ if (VersionChecker.isVersionLower(currentVersion, version)) {
Logger.logUpdateNotificationConsole();
- } else if (isVersionHigher(currentVersion, version)) {
+ } else if (VersionChecker.isVersionHigher(currentVersion, version)) {
Logger.logUnreleasedVersionNotification();
}
});
}
-
- public boolean isVersionLower(String current, String latest) {
- return compareVersions(current, latest) < 0;
- }
-
- public boolean isVersionHigher(String current, String latest) {
- return compareVersions(current, latest) > 0;
- }
-
- /**
- * Compares two version strings (e.g., "1.2.3" vs. "1.2.4").
- * Returns:
- * - A negative value if v1 < v2
- * - Zero if v1 == v2
- * - A positive value if v1 > v2
- */
- public int compareVersions(String v1, String v2) {
- String[] v1Parts = v1.split("\\.");
- String[] v2Parts = v2.split("\\.");
-
- int length = Math.max(v1Parts.length, v2Parts.length);
- for (int i = 0; i < length; i++) {
- int part1 = i < v1Parts.length ? Integer.parseInt(v1Parts[i]) : 0;
- int part2 = i < v2Parts.length ? Integer.parseInt(v2Parts[i]) : 0;
- if (part1 != part2) {
- return Integer.compare(part1, part2);
- }
- }
- return 0;
- }
}
\ No newline at end of file
diff --git a/src/main/java/net/jeqo/bloons/balloon/multipart/MultipartBalloonModel.java b/src/main/java/net/jeqo/bloons/balloon/multipart/MultipartBalloonModel.java
index 4717dc45..771f867e 100644
--- a/src/main/java/net/jeqo/bloons/balloon/multipart/MultipartBalloonModel.java
+++ b/src/main/java/net/jeqo/bloons/balloon/multipart/MultipartBalloonModel.java
@@ -43,7 +43,7 @@ public class MultipartBalloonModel {
public MultipartBalloonModel(BalloonSegmentType segmentType, String material, String color, int customModelData) {
this.setSegmentType(segmentType);
this.setMaterial(material);
- if (!color.equals(this.getColor()) && color != null && !color.isEmpty()) this.setColor(color);
+ if (!color.equals(this.getColor()) && !color.isEmpty()) this.setColor(color);
this.setCustomModelData(customModelData);
}
diff --git a/src/main/java/net/jeqo/bloons/balloon/single/SingleBalloon.java b/src/main/java/net/jeqo/bloons/balloon/single/SingleBalloon.java
index 465414c6..b759fa88 100644
--- a/src/main/java/net/jeqo/bloons/balloon/single/SingleBalloon.java
+++ b/src/main/java/net/jeqo/bloons/balloon/single/SingleBalloon.java
@@ -82,7 +82,11 @@ private void initializeBalloon() {
if (this.getType().getMegModelID() == null) {
// Create and set the balloons visual appearance/model
ItemMeta meta = this.getVisual().getItemMeta();
- meta.addItemFlags(ItemFlag.HIDE_UNBREAKABLE);
+
+ if (meta != null) {
+ meta.addItemFlags(ItemFlag.HIDE_UNBREAKABLE);
+ }
+
this.getVisual().setItemMeta(meta);
}
@@ -95,6 +99,13 @@ private void initializeBalloon() {
* Initializes the balloon's armor stand entity with the proper configurations
*/
public void initializeBalloonArmorStand() {
+ if (this.getPlayerLocation().getWorld() == null) {
+ Logger.logError("Player world is not currently set. Could not initialize balloon, removing from player.");
+ // Remove the balloon from the player
+ SingleBalloonManagement.removeBalloon(player, null);
+ return;
+ }
+
this.setArmorStand(this.getPlayerLocation().getWorld().spawn(this.getPlayerLocation(), ArmorStand.class));
this.getArmorStand().setBasePlate(false);
this.getArmorStand().setVisible(false);
@@ -105,7 +116,9 @@ public void initializeBalloonArmorStand() {
this.getArmorStand().setMarker(true);
this.getArmorStand().setCollidable(false);
if (this.getType().getMegModelID() == null) {
- this.getArmorStand().getEquipment().setHelmet(this.getVisual());
+ if (this.getArmorStand().getEquipment() != null) {
+ this.getArmorStand().getEquipment().setHelmet(this.getVisual());
+ }
} else {
try {
// Create the entity and tag it onto the armor stand
@@ -120,8 +133,7 @@ public void initializeBalloonArmorStand() {
// If an idle animation exists, play it initially
this.getAnimationHandler().playAnimation(this.getDefaultIdleAnimationID(), 0.3, 0.3, 1,true);
} catch (Exception e) {
- Logger.logError("An error occurred while creating the MEG model for the balloon " + this.getType().getId() + "! This is because a MEG model error occurred.");
- e.printStackTrace();
+ Logger.logError("An error occurred while creating the MEG model for the balloon " + this.getType().getId() + "! This is because a MEG model error occurred: " + e.getMessage());
}
}
this.getArmorStand().setCustomName(BalloonConfiguration.BALLOON_ARMOR_STAND_ID);
@@ -131,6 +143,13 @@ public void initializeBalloonArmorStand() {
* Initializes the balloon's lead to the player (chicken entity)
*/
public void initializeBalloonLead() {
+ if (this.getPlayerLocation().getWorld() == null) {
+ Logger.logError("Player world is not currently set. Could not initialize balloon, removing from player.");
+ // Remove the balloon from the player
+ SingleBalloonManagement.removeBalloon(player, null);
+ return;
+ }
+
this.setChicken(this.getPlayerLocation().getWorld().spawn(this.getPlayerLocation(), Chicken.class));
this.getChicken().setInvulnerable(true);
this.getChicken().setInvisible(true);
@@ -237,6 +256,8 @@ public synchronized void cancel() throws IllegalStateException {
* Spawns the particle effect when the balloon is removed
*/
public void spawnRemoveParticle() {
+ if (this.getMoveLocation().getWorld() == null) return;
+
this.getMoveLocation().getWorld().spawnParticle(Particle.CLOUD, this.getMoveLocation(), 5, 0.0D, 0.0D, 0.0D, 0.1D);
}
@@ -280,7 +301,10 @@ public ItemStack getConfiguredBalloonVisual(String balloonID) {
// Generate the item and set the custom model data meta
ItemStack item = new ItemStack(material);
ItemMeta meta = item.getItemMeta();
- meta.setCustomModelData(singleBalloonType.getCustomModelData());
+
+ if (meta != null) {
+ meta.setCustomModelData(singleBalloonType.getCustomModelData());
+ }
// If the color of the balloon is not set, log an error and return null
if (singleBalloonType.getColor() != null && singleBalloonType.getMaterial().startsWith(LEATHER_MATERIAL_PREFIX)) {
diff --git a/src/main/java/net/jeqo/bloons/commands/CommandEquip.java b/src/main/java/net/jeqo/bloons/commands/CommandEquip.java
index e28c67bb..19b7fe63 100644
--- a/src/main/java/net/jeqo/bloons/commands/CommandEquip.java
+++ b/src/main/java/net/jeqo/bloons/commands/CommandEquip.java
@@ -8,9 +8,10 @@
import net.jeqo.bloons.balloon.single.SingleBalloonType;
import net.jeqo.bloons.commands.manager.Command;
import net.jeqo.bloons.commands.manager.types.CommandPermission;
+import net.jeqo.bloons.logger.Logger;
+import net.jeqo.bloons.logger.LoggingLevel;
import net.jeqo.bloons.message.Languages;
import net.jeqo.bloons.management.SingleBalloonManagement;
-import net.jeqo.bloons.message.MessageTranslations;
import net.jeqo.bloons.management.MultipartBalloonManagement;
import org.bukkit.ChatColor;
import org.bukkit.Sound;
@@ -45,7 +46,6 @@ public boolean execute(CommandSender sender, String[] args) {
if (args.length < 1) usage(player);
String balloonID = args[0];
- MessageTranslations messageTranslations = new MessageTranslations(this.getPlugin());
// If the balloon ID isn't found in both balloon types, send a message to the player
if (Bloons.getBalloonCore().containsSingleBalloon(balloonID) && Bloons.getBalloonCore().containsMultipartBalloon(balloonID)) {
@@ -101,8 +101,13 @@ public boolean execute(CommandSender sender, String[] args) {
SingleBalloonManagement.removeBalloon(player, Bloons.getPlayerSingleBalloons().get(player.getUniqueId()));
SingleBalloon.checkBalloonRemovalOrAdd(player, balloonID);
- String equippedMessage = Languages.getMessage("prefix") + String.format(Languages.getMessage("equipped"), singleBalloonType.getName());
- player.sendMessage(ChatColor.translateAlternateColorCodes('&', equippedMessage));
+ if (singleBalloonType == null) {
+ Logger.logToPlayer(LoggingLevel.ERROR, player, "The current balloon type is null! Please correct this in the config.");
+ return false;
+ } else {
+ String equippedMessage = Languages.getMessage("prefix") + String.format(Languages.getMessage("equipped"), singleBalloonType.getName());
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', equippedMessage));
+ }
}
// Play a sound regardless of the balloon type and when it executes successfully
diff --git a/src/main/java/net/jeqo/bloons/commands/CommandForceEquip.java b/src/main/java/net/jeqo/bloons/commands/CommandForceEquip.java
index 16bfff3e..e89d6ed9 100644
--- a/src/main/java/net/jeqo/bloons/commands/CommandForceEquip.java
+++ b/src/main/java/net/jeqo/bloons/commands/CommandForceEquip.java
@@ -10,7 +10,6 @@
import net.jeqo.bloons.commands.manager.types.CommandPermission;
import net.jeqo.bloons.message.Languages;
import net.jeqo.bloons.management.SingleBalloonManagement;
-import net.jeqo.bloons.message.MessageTranslations;
import net.jeqo.bloons.management.MultipartBalloonManagement;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@@ -43,7 +42,6 @@ public boolean execute(CommandSender sender, String[] args) {
if (args.length < 1) usage(sender);
Player player = Bukkit.getPlayer(args[0]);
- MessageTranslations messageTranslations = new MessageTranslations(this.getPlugin());
// If the player isn't found, send a message to the sender
if (player == null) {
diff --git a/src/main/java/net/jeqo/bloons/commands/CommandForceUnequip.java b/src/main/java/net/jeqo/bloons/commands/CommandForceUnequip.java
index 520331c5..f5c74f05 100644
--- a/src/main/java/net/jeqo/bloons/commands/CommandForceUnequip.java
+++ b/src/main/java/net/jeqo/bloons/commands/CommandForceUnequip.java
@@ -7,7 +7,6 @@
import net.jeqo.bloons.commands.manager.types.CommandPermission;
import net.jeqo.bloons.message.Languages;
import net.jeqo.bloons.management.SingleBalloonManagement;
-import net.jeqo.bloons.message.MessageTranslations;
import net.jeqo.bloons.management.MultipartBalloonManagement;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@@ -27,7 +26,6 @@ public CommandForceUnequip(JavaPlugin plugin) {
@Override
public boolean execute(CommandSender sender, String[] args) {
- MessageTranslations messageTranslations = new MessageTranslations(this.getPlugin());
Player player = Bukkit.getPlayer(args[0]);
// If the specified player doesn't exist, send a message to the sender
diff --git a/src/main/java/net/jeqo/bloons/commands/CommandReload.java b/src/main/java/net/jeqo/bloons/commands/CommandReload.java
index 3204f4f1..655cb25b 100644
--- a/src/main/java/net/jeqo/bloons/commands/CommandReload.java
+++ b/src/main/java/net/jeqo/bloons/commands/CommandReload.java
@@ -4,7 +4,6 @@
import net.jeqo.bloons.commands.manager.Command;
import net.jeqo.bloons.commands.manager.types.CommandPermission;
import net.jeqo.bloons.message.Languages;
-import net.jeqo.bloons.message.MessageTranslations;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
@@ -29,8 +28,6 @@ public CommandReload(JavaPlugin plugin) {
@Override
public boolean execute(CommandSender sender, String[] args) {
- MessageTranslations messageTranslations = new MessageTranslations(this.getPlugin());
-
// Reload the main config.yml and its defaults
Bloons.getInstance().reloadConfig();
Bloons.getInstance().getConfig().options().copyDefaults();
diff --git a/src/main/java/net/jeqo/bloons/commands/CommandUnequip.java b/src/main/java/net/jeqo/bloons/commands/CommandUnequip.java
index 7fd8e4d1..1af0d76b 100644
--- a/src/main/java/net/jeqo/bloons/commands/CommandUnequip.java
+++ b/src/main/java/net/jeqo/bloons/commands/CommandUnequip.java
@@ -7,7 +7,6 @@
import net.jeqo.bloons.commands.manager.types.CommandPermission;
import net.jeqo.bloons.message.Languages;
import net.jeqo.bloons.management.SingleBalloonManagement;
-import net.jeqo.bloons.message.MessageTranslations;
import net.jeqo.bloons.management.MultipartBalloonManagement;
import org.bukkit.ChatColor;
import org.bukkit.Sound;
diff --git a/src/main/java/net/jeqo/bloons/commands/manager/CommandCore.java b/src/main/java/net/jeqo/bloons/commands/manager/CommandCore.java
index bc06e19d..4803d0bb 100644
--- a/src/main/java/net/jeqo/bloons/commands/manager/CommandCore.java
+++ b/src/main/java/net/jeqo/bloons/commands/manager/CommandCore.java
@@ -113,7 +113,7 @@ public boolean onCommand(@NotNull CommandSender sender, org.bukkit.command.@NotN
ArrayList singleBalloonTypes = Bloons.getBalloonCore().getSingleBalloonTypes();
ArrayList multipartBalloonTypes = Bloons.getBalloonCore().getMultipartBalloonTypes();
- //
+ // Check if none are registered
if (singleBalloonTypes == null && multipartBalloonTypes == null) {
Logger.logError(ChatColor.translateAlternateColorCodes('&', Languages.getMessage("no-balloons-registered")));
return false;
diff --git a/src/main/java/net/jeqo/bloons/commands/utils/ErrorHandling.java b/src/main/java/net/jeqo/bloons/commands/utils/ErrorHandling.java
index 568b327e..5822af34 100644
--- a/src/main/java/net/jeqo/bloons/commands/utils/ErrorHandling.java
+++ b/src/main/java/net/jeqo/bloons/commands/utils/ErrorHandling.java
@@ -2,7 +2,6 @@
import net.jeqo.bloons.Bloons;
import net.jeqo.bloons.configuration.PluginConfiguration;
-import net.jeqo.bloons.message.MessageTranslations;
import org.bukkit.command.CommandSender;
/**
@@ -16,9 +15,6 @@ public class ErrorHandling {
* @param sender The sender of the command, type org.bukkit.command.CommandSender
*/
public static void usage(CommandSender sender) {
- // MessageTranslations will need to adapt for plain text
- MessageTranslations messageTranslations = new MessageTranslations(Bloons.getInstance());
-
sender.sendMessage(""); // Blank line for spacing
if (sender.hasPermission("bloons.menu")) {
String menuMessage = " §d/bloons §7- Open the balloon menu";
diff --git a/src/main/java/net/jeqo/bloons/configuration/ConfigConfiguration.java b/src/main/java/net/jeqo/bloons/configuration/ConfigConfiguration.java
index defdcbec..61e150fc 100644
--- a/src/main/java/net/jeqo/bloons/configuration/ConfigConfiguration.java
+++ b/src/main/java/net/jeqo/bloons/configuration/ConfigConfiguration.java
@@ -13,7 +13,6 @@
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
-import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
diff --git a/src/main/java/net/jeqo/bloons/configuration/PluginConfiguration.java b/src/main/java/net/jeqo/bloons/configuration/PluginConfiguration.java
index 9362a022..fcb9f2fe 100644
--- a/src/main/java/net/jeqo/bloons/configuration/PluginConfiguration.java
+++ b/src/main/java/net/jeqo/bloons/configuration/PluginConfiguration.java
@@ -13,6 +13,9 @@ public class PluginConfiguration {
// The base prefix to all commands within the plugin
public static final String COMMAND_BASE = "bloons";
+ // The bStats plugin resource ID used for metrics
+ public static final int BSTATS_PLUGIN_ID = 16872;
+
/**
* Get the version of the plugin from the pom.xml file
* @return The version of the plugin, type java.lang.String
diff --git a/src/main/java/net/jeqo/bloons/item/NBTItem.java b/src/main/java/net/jeqo/bloons/item/NBTItem.java
index 4596f8c6..0824eeb3 100644
--- a/src/main/java/net/jeqo/bloons/item/NBTItem.java
+++ b/src/main/java/net/jeqo/bloons/item/NBTItem.java
@@ -9,6 +9,8 @@
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
+import java.util.Optional;
+
/**
* An extension of an Item with the utilities to manage NBT
* data easier and more efficiently
@@ -32,6 +34,8 @@ public NBTItem(ItemStack item) {
*/
public boolean hasKey(String key) {
NamespacedKey nbtKey = new NamespacedKey(Bloons.getInstance(), key);
+
+ if (this.getItem().getItemMeta() == null) return false;
PersistentDataContainer container = this.getItem().getItemMeta().getPersistentDataContainer();
return container.getKeys().contains(nbtKey);
@@ -45,7 +49,8 @@ public boolean hasKey(String key) {
public void setStringFlag(String key, String value) {
NamespacedKey nbtKey = new NamespacedKey(Bloons.getInstance(), key);
- ItemMeta meta = getItem().getItemMeta();
+ ItemMeta meta = this.getItem().getItemMeta();
+ if (meta == null) return;
meta.getPersistentDataContainer().set(nbtKey, PersistentDataType.STRING, value);
this.getItem().setItemMeta(meta);
@@ -58,6 +63,7 @@ public void setStringFlag(String key, String value) {
*/
public String getStringFlag(String key) {
NamespacedKey nbtKey = new NamespacedKey(Bloons.getInstance(), key);
+ if (this.getItem().getItemMeta() == null) return "";
PersistentDataContainer container = this.getItem().getItemMeta().getPersistentDataContainer();
if (!container.has(nbtKey, PersistentDataType.STRING)) return null;
@@ -74,6 +80,7 @@ public void setIntegerFlag(String key, int value) {
NamespacedKey nbtKey = new NamespacedKey(Bloons.getInstance(), key);
ItemMeta meta = this.getItem().getItemMeta();
+ if (meta == null) return;
meta.getPersistentDataContainer().set(nbtKey, PersistentDataType.INTEGER, value);
this.getItem().setItemMeta(meta);
@@ -86,11 +93,12 @@ public void setIntegerFlag(String key, int value) {
*/
public int getIntegerFlag(String key) {
NamespacedKey nbtKey = new NamespacedKey(Bloons.getInstance(), key);
+ if (this.getItem().getItemMeta() == null) return 0;
PersistentDataContainer container = this.getItem().getItemMeta().getPersistentDataContainer();
if (!container.has(nbtKey, PersistentDataType.INTEGER)) return 0;
- return container.get(nbtKey, PersistentDataType.INTEGER);
+ return Optional.ofNullable(container.get(nbtKey, PersistentDataType.INTEGER)).orElse(0);
}
/**
@@ -102,6 +110,7 @@ public void setDoubleFlag(String key, double value) {
NamespacedKey nbtKey = new NamespacedKey(Bloons.getInstance(), key);
ItemMeta meta = this.getItem().getItemMeta();
+ if (meta == null) return;
meta.getPersistentDataContainer().set(nbtKey, PersistentDataType.DOUBLE, value);
this.getItem().setItemMeta(meta);
@@ -114,11 +123,12 @@ public void setDoubleFlag(String key, double value) {
*/
public double getDoubleFlag(String key) {
NamespacedKey nbtKey = new NamespacedKey(Bloons.getInstance(), key);
+ if (this.getItem().getItemMeta() == null) return 0.0;
PersistentDataContainer container = this.getItem().getItemMeta().getPersistentDataContainer();
if (!container.has(nbtKey, PersistentDataType.DOUBLE)) return 0.0;
- return container.get(nbtKey, PersistentDataType.DOUBLE);
+ return Optional.ofNullable(container.get(nbtKey, PersistentDataType.DOUBLE)).orElse(0.0);
}
/**
@@ -130,6 +140,7 @@ public void setBooleanFlag(String key, boolean value) {
NamespacedKey nbtKey = new NamespacedKey(Bloons.getInstance(), key);
ItemMeta meta = this.getItem().getItemMeta();
+ if (meta == null) return;
meta.getPersistentDataContainer().set(nbtKey, PersistentDataType.BOOLEAN, value);
this.getItem().setItemMeta(meta);
@@ -142,6 +153,7 @@ public void setBooleanFlag(String key, boolean value) {
*/
public boolean getBooleanFlag(String key) {
NamespacedKey nbtKey = new NamespacedKey(Bloons.getInstance(), key);
+ if (this.getItem().getItemMeta() == null) return false;
PersistentDataContainer container = this.getItem().getItemMeta().getPersistentDataContainer();
if (!container.has(nbtKey, PersistentDataType.BOOLEAN)) return false;
diff --git a/src/main/java/net/jeqo/bloons/listeners/BalloonEntityListener.java b/src/main/java/net/jeqo/bloons/listeners/BalloonChickenEntityListener.java
similarity index 92%
rename from src/main/java/net/jeqo/bloons/listeners/BalloonEntityListener.java
rename to src/main/java/net/jeqo/bloons/listeners/BalloonChickenEntityListener.java
index 618e8ad6..6cb0888f 100644
--- a/src/main/java/net/jeqo/bloons/listeners/BalloonEntityListener.java
+++ b/src/main/java/net/jeqo/bloons/listeners/BalloonChickenEntityListener.java
@@ -8,7 +8,7 @@
/**
* A class that listens for events related to balloon entities
*/
-public class BalloonEntityListener implements Listener {
+public class BalloonChickenEntityListener implements Listener {
/**
* Stop the chicken from going through the portal to prevent unleashing from player to balloon
diff --git a/src/main/java/net/jeqo/bloons/listeners/BalloonUnleashListener.java b/src/main/java/net/jeqo/bloons/listeners/BalloonChickenLeashListener.java
similarity index 92%
rename from src/main/java/net/jeqo/bloons/listeners/BalloonUnleashListener.java
rename to src/main/java/net/jeqo/bloons/listeners/BalloonChickenLeashListener.java
index cd903acd..57e71ca2 100644
--- a/src/main/java/net/jeqo/bloons/listeners/BalloonUnleashListener.java
+++ b/src/main/java/net/jeqo/bloons/listeners/BalloonChickenLeashListener.java
@@ -3,14 +3,13 @@
import net.jeqo.bloons.configuration.BalloonConfiguration;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
-import org.bukkit.event.entity.EntityUnleashEvent;
import org.bukkit.event.entity.PlayerLeashEntityEvent;
import org.bukkit.event.player.PlayerUnleashEntityEvent;
/**
* A class that listens for events related to balloon unleashing and leashing
*/
-public class BalloonUnleashListener implements Listener {
+public class BalloonChickenLeashListener implements Listener {
/**
* Used to check if player tries to unleash from their balloon, if they do then cancel it
diff --git a/src/main/java/net/jeqo/bloons/listeners/PlayerUpdateNotificationListener.java b/src/main/java/net/jeqo/bloons/listeners/PlayerUpdateNotificationListener.java
new file mode 100644
index 00000000..c834ba5a
--- /dev/null
+++ b/src/main/java/net/jeqo/bloons/listeners/PlayerUpdateNotificationListener.java
@@ -0,0 +1,30 @@
+package net.jeqo.bloons.listeners;
+
+import net.jeqo.bloons.Bloons;
+import net.jeqo.bloons.health.UpdateChecker;
+import net.jeqo.bloons.logger.Logger;
+import net.jeqo.bloons.utils.VersionChecker;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerJoinEvent;
+
+public class PlayerUpdateNotificationListener implements Listener {
+
+ @EventHandler
+ public void onPlayerJoin(PlayerJoinEvent event) {
+ if (event.getPlayer().isOp()) {
+ if (Bloons.getInstance().getConfig().getBoolean("check-for-updates")) {
+ // Check for an update if the player is an operator on the server
+ new UpdateChecker(Bloons.getInstance(), 106243).getVersion(version -> {
+ String currentVersion = Bloons.getInstance().getDescription().getVersion();
+
+ if (VersionChecker.isVersionLower(currentVersion, version)) {
+ Logger.logUpdateNotificationPlayer(event.getPlayer());
+ } else if (VersionChecker.isVersionHigher(currentVersion, version)) {
+ Logger.logUnreleasedVersionNotificationPlayer(event.getPlayer());
+ }
+ });
+ }
+ }
+ }
+}
diff --git a/src/main/java/net/jeqo/bloons/listeners/single/SingleBalloonPlayerJoinListener.java b/src/main/java/net/jeqo/bloons/listeners/single/SingleBalloonPlayerJoinListener.java
new file mode 100644
index 00000000..50e40851
--- /dev/null
+++ b/src/main/java/net/jeqo/bloons/listeners/single/SingleBalloonPlayerJoinListener.java
@@ -0,0 +1,27 @@
+package net.jeqo.bloons.listeners.single;
+
+import net.jeqo.bloons.Bloons;
+import net.jeqo.bloons.balloon.single.SingleBalloon;
+import net.jeqo.bloons.management.SingleBalloonManagement;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerJoinEvent;
+
+public class SingleBalloonPlayerJoinListener implements Listener {
+
+ /**
+ * When a player joins, add the balloon back if they left with one, or just don't add anything
+ * @param event The event that is called when a player joins the server, type org.bukkit.event.player.PlayerJoinEvent
+ */
+ @EventHandler
+ public void onPlayerJoin(PlayerJoinEvent event) {
+ String balloonID = Bloons.getPlayerSingleBalloonID().get(event.getPlayer().getUniqueId());
+
+ // If they have a balloon active, remove it and add it back to reduce issues
+ if (balloonID != null) {
+ SingleBalloonManagement.removeBalloon(event.getPlayer(), Bloons.getPlayerSingleBalloons().get(event.getPlayer().getUniqueId()));
+
+ SingleBalloon.checkBalloonRemovalOrAdd(event.getPlayer(), balloonID);
+ }
+ }
+}
diff --git a/src/main/java/net/jeqo/bloons/listeners/single/SingleBalloonPlayerLeaveListener.java b/src/main/java/net/jeqo/bloons/listeners/single/SingleBalloonPlayerLeaveListener.java
new file mode 100644
index 00000000..4c39aae0
--- /dev/null
+++ b/src/main/java/net/jeqo/bloons/listeners/single/SingleBalloonPlayerLeaveListener.java
@@ -0,0 +1,22 @@
+package net.jeqo.bloons.listeners.single;
+
+import net.jeqo.bloons.Bloons;
+import net.jeqo.bloons.balloon.single.SingleBalloon;
+import net.jeqo.bloons.management.SingleBalloonManagement;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerQuitEvent;
+
+public class SingleBalloonPlayerLeaveListener implements Listener {
+
+ /**
+ * When a player quits, make sure to despawn and store their balloon in storage
+ * @param event The event that is called when a player quits the server, type org.bukkit.event.player.PlayerQuitEvent
+ */
+ @EventHandler
+ public void onPlayerLeave(PlayerQuitEvent event) {
+ SingleBalloon owner = Bloons.getPlayerSingleBalloons().get(event.getPlayer().getUniqueId());
+
+ SingleBalloonManagement.storeBalloon(owner);
+ }
+}
diff --git a/src/main/java/net/jeqo/bloons/listeners/single/SingleBalloonPlayerListener.java b/src/main/java/net/jeqo/bloons/listeners/single/SingleBalloonPlayerListener.java
index 76ab2e64..faff55a9 100644
--- a/src/main/java/net/jeqo/bloons/listeners/single/SingleBalloonPlayerListener.java
+++ b/src/main/java/net/jeqo/bloons/listeners/single/SingleBalloonPlayerListener.java
@@ -2,65 +2,17 @@
import net.jeqo.bloons.Bloons;
import net.jeqo.bloons.balloon.single.SingleBalloon;
-import net.jeqo.bloons.health.UpdateChecker;
-import net.jeqo.bloons.logger.Logger;
import net.jeqo.bloons.management.SingleBalloonManagement;
-import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerChangedWorldEvent;
-import org.bukkit.event.player.PlayerJoinEvent;
-import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import java.util.Objects;
public class SingleBalloonPlayerListener implements Listener {
- /**
- * When a player quits, make sure to despawn and store their balloon in storage
- * @param event The event that is called when a player quits the server, type org.bukkit.event.player.PlayerQuitEvent
- */
- @EventHandler
- public void onQuit(PlayerQuitEvent event) {
- SingleBalloon owner = Bloons.getPlayerSingleBalloons().get(event.getPlayer().getUniqueId());
-
- SingleBalloonManagement.storeBalloon(owner);
- }
-
- /**
- * When a player joins, add the balloon back if they left with one, or just don't add anything
- * @param event The event that is called when a player joins the server, type org.bukkit.event.player.PlayerJoinEvent
- */
- @EventHandler
- public void onJoin(PlayerJoinEvent event) {
- Player player = event.getPlayer();
- String balloonID = Bloons.getPlayerSingleBalloonID().get(event.getPlayer().getUniqueId());
-
- // If they have a balloon active, remove it and add it back to reduce issues
- if (balloonID != null) {
- SingleBalloonManagement.removeBalloon(event.getPlayer(), Bloons.getPlayerSingleBalloons().get(event.getPlayer().getUniqueId()));
-
- SingleBalloon.checkBalloonRemovalOrAdd(event.getPlayer(), balloonID);
- }
-
- if (event.getPlayer().isOp()) {
- if (Bloons.getInstance().getConfig().getBoolean("check-for-updates")) {
- // Check for an update if the player is an operator on the server
- new UpdateChecker(Bloons.getInstance(), 106243).getVersion(version -> {
- String currentVersion = Bloons.getInstance().getDescription().getVersion();
-
- if (Bloons.getInstance().isVersionLower(currentVersion, version)) {
- Logger.logUpdateNotificationPlayer(event.getPlayer());
- } else if (Bloons.getInstance().isVersionHigher(currentVersion, version)) {
- Logger.logUnreleasedVersionNotificationPlayer(event.getPlayer());
- }
- });
- }
- }
- }
-
/**
* When they die, remove their balloon
* @param event The event that is called when a player dies, type org.bukkit.event.entity.PlayerDeathEvent
diff --git a/src/main/java/net/jeqo/bloons/logger/Logger.java b/src/main/java/net/jeqo/bloons/logger/Logger.java
index a12d3812..47b2e629 100644
--- a/src/main/java/net/jeqo/bloons/logger/Logger.java
+++ b/src/main/java/net/jeqo/bloons/logger/Logger.java
@@ -3,8 +3,6 @@
import net.jeqo.bloons.Bloons;
import net.jeqo.bloons.configuration.ConfigConfiguration;
import net.jeqo.bloons.configuration.PluginConfiguration;
-import net.jeqo.bloons.message.Languages;
-import net.jeqo.bloons.message.MessageTranslations;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
diff --git a/src/main/java/net/jeqo/bloons/management/SingleBalloonManagement.java b/src/main/java/net/jeqo/bloons/management/SingleBalloonManagement.java
index 1d617067..58d130a5 100644
--- a/src/main/java/net/jeqo/bloons/management/SingleBalloonManagement.java
+++ b/src/main/java/net/jeqo/bloons/management/SingleBalloonManagement.java
@@ -23,19 +23,6 @@ public static void removeBalloon(Player player, SingleBalloon owner) {
Bloons.getPlayerSingleBalloonID().remove(player.getUniqueId());
}
- /**
- * Remove the balloon from the player quickly
- * @param player The player to remove the balloon from, type org.bukkit.entity.Player
- * @param owner The balloon, type net.jeqo.bloons.balloon.single.SingleBalloon
- */
- public static void quickRemoveBalloon(Player player, SingleBalloon owner) {
- if (owner == null) return;
-
- owner.cancel();
- Bloons.getPlayerSingleBalloons().remove(player.getUniqueId());
- Bloons.getPlayerSingleBalloonID().remove(player.getUniqueId());
- }
-
/**
* Store the balloon in storage and just cancel the runnable
* @param balloon The balloon, type net.jeqo.bloons.balloon.single.SingleBalloon
diff --git a/src/main/java/net/jeqo/bloons/utils/VersionChecker.java b/src/main/java/net/jeqo/bloons/utils/VersionChecker.java
new file mode 100644
index 00000000..57247604
--- /dev/null
+++ b/src/main/java/net/jeqo/bloons/utils/VersionChecker.java
@@ -0,0 +1,34 @@
+package net.jeqo.bloons.utils;
+
+public class VersionChecker {
+
+ public static boolean isVersionLower(String current, String latest) {
+ return compareVersions(current, latest) < 0;
+ }
+
+ public static boolean isVersionHigher(String current, String latest) {
+ return compareVersions(current, latest) > 0;
+ }
+
+ /**
+ * Compares two version strings (e.g., "1.2.3" vs. "1.2.4").
+ * Returns:
+ * - A negative value if v1 < v2
+ * - Zero if v1 == v2
+ * - A positive value if v1 > v2
+ */
+ public static int compareVersions(String v1, String v2) {
+ String[] v1Parts = v1.split("\\.");
+ String[] v2Parts = v2.split("\\.");
+
+ int length = Math.max(v1Parts.length, v2Parts.length);
+ for (int i = 0; i < length; i++) {
+ int part1 = i < v1Parts.length ? Integer.parseInt(v1Parts[i]) : 0;
+ int part2 = i < v2Parts.length ? Integer.parseInt(v2Parts[i]) : 0;
+ if (part1 != part2) {
+ return Integer.compare(part1, part2);
+ }
+ }
+ return 0;
+ }
+}