-
-
-
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index 359d5c263..5e4423607 100644
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -11,11 +11,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -27,14 +52,9 @@
-
-
-
-
-
-
-
-
+
+
+
@@ -46,11 +66,6 @@
-
-
-
-
-
diff --git a/.idea/misc.xml b/.idea/misc.xml
index f97235f3f..1690356b5 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -22,7 +22,7 @@
-
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index e3af66b46..425c3dc11 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,14 +10,14 @@
me.lokka30LevelledMobs
- 3.2.6 b576
+ 3.3.0 b579jarLevelledMobsThe Ultimate RPG Mob Levelling Plugin
- 1.8
+ 11UTF-8
@@ -62,6 +62,7 @@
+ true
@@ -71,6 +72,11 @@
false
+
+
+ *:*
+
+
@@ -85,6 +91,14 @@
+
+ essentials-releases
+ https://repo.essentialsx.net/releases/
+
+
+ papermc
+ https://papermc.io/repo/repository/maven-public/
+ placeholderapihttps://repo.extendedclip.com/content/repositories/placeholderapi/
@@ -120,6 +134,18 @@
+
+ net.essentialsx
+ EssentialsX
+ 2.19.0
+ provided
+
+
+ io.papermc.paper
+ paper-api
+ 1.17.1-R0.1-SNAPSHOT
+ provided
+ me.clipplaceholderapi
@@ -153,7 +179,8 @@
com.github.lokka30MicroLib
- 2.3.1
+ 3.2.0
+ compilecom.github.dmulloy2
@@ -170,7 +197,13 @@
simplepets.brainsynderAPI
- 5.0-BUILD-89
+ 5.0-BUILD-98
+ provided
+
+
+ com.google.code.gson
+ gson
+ 2.8.9provided
diff --git a/src/main/java/me/lokka30/levelledmobs/Companion.java b/src/main/java/me/lokka30/levelledmobs/Companion.java
index b17866423..fed26c2ca 100644
--- a/src/main/java/me/lokka30/levelledmobs/Companion.java
+++ b/src/main/java/me/lokka30/levelledmobs/Companion.java
@@ -12,23 +12,22 @@
import me.lokka30.levelledmobs.managers.ExternalCompatibilityManager;
import me.lokka30.levelledmobs.managers.LevelManager;
import me.lokka30.levelledmobs.managers.PlaceholderApiIntegration;
-import me.lokka30.levelledmobs.managers.WorldGuardIntegration;
-import me.lokka30.levelledmobs.misc.FileLoader;
-import me.lokka30.levelledmobs.misc.FileMigrator;
-import me.lokka30.levelledmobs.misc.Utils;
-import me.lokka30.levelledmobs.misc.VersionInfo;
+import me.lokka30.levelledmobs.misc.*;
import me.lokka30.levelledmobs.rules.MetricsInfo;
-import me.lokka30.microlib.UpdateChecker;
-import me.lokka30.microlib.VersionUtils;
+import me.lokka30.microlib.exceptions.OutdatedServerVersionException;
+import me.lokka30.microlib.other.UpdateChecker;
+import me.lokka30.microlib.other.VersionUtils;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.SimpleBarChart;
import org.bstats.charts.SimplePie;
import org.bukkit.Bukkit;
+import org.bukkit.Location;
import org.bukkit.command.PluginCommand;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
+import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import java.io.*;
@@ -50,33 +49,28 @@ public class Companion {
Companion(final LevelledMobs main) {
this.main = main;
this.recentlyJoinedPlayers = new WeakHashMap<>();
+ this.playerNetherPortals = new HashMap<>();
this.updateResult = new LinkedList<>();
buildUniversalGroups();
this.metricsInfo = new MetricsInfo(main);
this.spawner_CopyIds = new LinkedList<>();
this.spawner_InfoIds = new LinkedList<>();
+ this.debugsEnabled = new LinkedList<>();
}
final private WeakHashMap recentlyJoinedPlayers;
public HashSet groups_HostileMobs;
public HashSet groups_AquaticMobs;
public HashSet groups_PassiveMobs;
- public HashSet groups_NetherMobs;
public List updateResult;
+ final public Map playerNetherPortals;
final public List spawner_CopyIds;
final public List spawner_InfoIds;
- public boolean playerInteractListenerIsRegistered;
+ final public List debugsEnabled;
final private PluginManager pluginManager = Bukkit.getPluginManager();
final private MetricsInfo metricsInfo;
final static private Object playerLogonTimes_Lock = new Object();
-
- void checkWorldGuard() {
- // Hook into WorldGuard
- // This cannot be moved to onEnable (stated in WorldGuard's documentation). It MUST be ran in onLoad.
- if (ExternalCompatibilityManager.hasWorldGuardInstalled()) {
- main.worldGuardIntegration = new WorldGuardIntegration();
- }
- }
+ final static private Object playerNetherPortals_Lock = new Object();
//Checks if the server version is supported
public void checkCompatibility() {
@@ -113,7 +107,7 @@ private int getSettingsVersion(){
}
// Note: also called by the reload subcommand.
- public boolean loadFiles(final boolean isReload) {
+ boolean loadFiles(final boolean isReload) {
Utils.logger.info("&fFile Loader: &7Loading files...");
// save license.txt
@@ -149,20 +143,19 @@ public boolean loadFiles(final boolean isReload) {
// remove legacy files if they exist
final String[] legacyFile = {"attributes.yml", "drops.yml"};
- for (String lFile : legacyFile) {
+ for (final String lFile : legacyFile) {
final File delFile = new File(main.getDataFolder(), lFile);
try {
- if (delFile.exists()) delFile.delete();
- } catch (Exception e) {
+ if (delFile.exists()) //noinspection ResultOfMethodCallIgnored
+ delFile.delete();
+ } catch (final Exception e) {
Utils.logger.warning("Unable to delete file " + lFile + ", " + e.getMessage());
}
}
}
- final List debugsEnabled = main.settingsCfg.getStringList(main.helperSettings.getKeyNameFromConfig(main.settingsCfg, "debug-misc"));
- if (!debugsEnabled.isEmpty())
- Utils.logger.info("misc debugs enabled: &b" + debugsEnabled);
+ parseDebugsEnabled();
main.configUtils.load();
main.playerLevellingMinRelevelTime = main.helperSettings.getInt(main.settingsCfg, "player-levelling-relevel-min-time", 5000);
@@ -170,18 +163,39 @@ public boolean loadFiles(final boolean isReload) {
return true;
}
+ private void parseDebugsEnabled(){
+ this.debugsEnabled.clear();
+
+ final List debugsEnabled = main.settingsCfg.getStringList(main.helperSettings.getKeyNameFromConfig(main.settingsCfg, "debug-misc"));
+ if (debugsEnabled.isEmpty()) return;
+
+ for (final String debug : debugsEnabled){
+ if (Utils.isNullOrEmpty(debug)) continue;
+
+ try {
+ final DebugType debugType = DebugType.valueOf(debug.toUpperCase());
+ this.debugsEnabled.add(debugType);
+ } catch (final Exception ignored) {
+ Utils.logger.warning("Invalid value for debug-misc: " + debug);
+ }
+ }
+
+ if (!this.debugsEnabled.isEmpty())
+ Utils.logger.info("debug-misc items enabled: &b" + this.debugsEnabled);
+ }
+
@Nullable
- YamlConfiguration loadEmbeddedResource(final String filename) {
+ private YamlConfiguration loadEmbeddedResource(final String filename) {
YamlConfiguration result = null;
final InputStream inputStream = main.getResource(filename);
if (inputStream == null) return null;
try {
- InputStreamReader reader = new InputStreamReader(inputStream);
+ final InputStreamReader reader = new InputStreamReader(inputStream);
result = YamlConfiguration.loadConfiguration(reader);
reader.close();
inputStream.close();
- } catch (IOException e) {
+ } catch (final IOException e) {
Utils.logger.error("Error reading embedded file: " + filename + ", " + e.getMessage());
}
@@ -217,8 +231,10 @@ void registerListeners() {
pluginManager.registerEvents(new PlayerDeathListener(main), main);
pluginManager.registerEvents(new CombustListener(main), main);
pluginManager.registerEvents(main.blockPlaceListener, main);
+ pluginManager.registerEvents(new PlayerPortalEventListener(main), main);
main.chunkLoadListener = new ChunkLoadListener(main);
main.playerInteractEventListener = new PlayerInteractEventListener(main);
+ pluginManager.registerEvents(main.playerInteractEventListener, main);
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
main.placeholderApiIntegration = new PlaceholderApiIntegration(main);
@@ -232,12 +248,12 @@ void registerListeners() {
void registerCommands() {
Utils.logger.info("&fCommands: &7Registering commands...");
+ main.levelledMobsCommand = new LevelledMobsCommand(main);
final PluginCommand levelledMobsCommand = main.getCommand("levelledmobs");
- if (levelledMobsCommand == null) {
+ if (levelledMobsCommand == null)
Utils.logger.error("Command &b/levelledmobs&7 is unavailable, is it not registered in plugin.yml?");
- } else {
- levelledMobsCommand.setExecutor(new LevelledMobsCommand(main));
- }
+ else
+ levelledMobsCommand.setExecutor(main.levelledMobsCommand);
}
void loadSpigotConfig(){
@@ -245,7 +261,7 @@ void loadSpigotConfig(){
main.levelManager.attributeMaxHealthMax = Bukkit.getServer().spigot().getConfig().getDouble("settings.attribute.maxHealth.max", 2048.0);
main.levelManager.attributeMovementSpeedMax = Bukkit.getServer().spigot().getConfig().getDouble("settings.attribute.movementSpeed.max", 2048.0);
main.levelManager.attributeAttackDamageMax = Bukkit.getServer().spigot().getConfig().getDouble("settings.attribute.attackDamage.max", 2048.0);
- } catch (NoSuchMethodError ignored) {
+ } catch (final NoSuchMethodError ignored) {
main.levelManager.attributeMaxHealthMax = Integer.MAX_VALUE;
main.levelManager.attributeMovementSpeedMax = Integer.MAX_VALUE;
main.levelManager.attributeAttackDamageMax = Integer.MAX_VALUE;
@@ -274,68 +290,73 @@ void setupMetrics() {
void checkUpdates() {
if (main.helperSettings.getBoolean(main.settingsCfg,"use-update-checker", true)) {
final UpdateChecker updateChecker = new UpdateChecker(main, 74304);
- updateChecker.getLatestVersion(latestVersion -> {
- final String currentVersion = updateChecker.getCurrentVersion().split(" ")[0];
-
- VersionInfo thisVersion;
- VersionInfo spigotVersion;
- boolean isOutOfDate;
- boolean isNewerVersion;
-
- try {
- thisVersion = new VersionInfo(currentVersion);
- spigotVersion = new VersionInfo(latestVersion);
-
- isOutOfDate = (thisVersion.compareTo(spigotVersion) < 0);
- isNewerVersion = (thisVersion.compareTo(spigotVersion) > 0);
- } catch (InvalidObjectException e) {
- Utils.logger.warning("Got exception creating version objects: " + e.getMessage());
-
- isOutOfDate = !currentVersion.equals(latestVersion);
- isNewerVersion = currentVersion.contains("indev");
- }
-
- if (isNewerVersion) {
- updateResult = Collections.singletonList(
- "&7Your &bLevelledMobs&7 version is &ba pre-release&7. Latest release version is &bv%latestVersion%&7. &8(&7You're running &bv%currentVersion%&8)");
-
- updateResult = Utils.replaceAllInList(updateResult, "%currentVersion%", currentVersion);
- updateResult = Utils.replaceAllInList(updateResult, "%latestVersion%", latestVersion);
- updateResult = Utils.colorizeAllInList(updateResult);
-
- updateResult.forEach(Utils.logger::warning);
- } else if (isOutOfDate) {
-
- // for some reason config#getStringList doesn't allow defaults??
- if (main.messagesCfg.contains("other.update-notice.messages")) {
- updateResult = main.messagesCfg.getStringList("other.update-notice.messages");
- } else {
- updateResult = Arrays.asList(
- "&b&nLevelledMobs Update Checker Notice:",
- "&7Your &bLevelledMobs&7 version is &boutdated&7! Please update to" +
- "&bv%latestVersion%&7 as soon as possible. &8(&7You''re running &bv%currentVersion%&8)");
+ try {
+ updateChecker.getLatestVersion(latestVersion -> {
+ final String currentVersion = updateChecker.getCurrentVersion().split(" ")[0];
+
+ final VersionInfo thisVersion;
+ final VersionInfo spigotVersion;
+ boolean isOutOfDate;
+ boolean isNewerVersion;
+
+ try {
+ thisVersion = new VersionInfo(currentVersion);
+ spigotVersion = new VersionInfo(latestVersion);
+
+ isOutOfDate = (thisVersion.compareTo(spigotVersion) < 0);
+ isNewerVersion = (thisVersion.compareTo(spigotVersion) > 0);
+ } catch (final InvalidObjectException e) {
+ Utils.logger.warning("Got exception creating version objects: " + e.getMessage());
+
+ isOutOfDate = !currentVersion.equals(latestVersion);
+ isNewerVersion = currentVersion.contains("indev");
}
- updateResult = Utils.replaceAllInList(updateResult, "%currentVersion%", currentVersion);
- updateResult = Utils.replaceAllInList(updateResult, "%latestVersion%", latestVersion);
- updateResult = Utils.colorizeAllInList(updateResult);
+ if (isNewerVersion) {
+ updateResult = Collections.singletonList(
+ "&7Your &bLevelledMobs&7 version is &ba pre-release&7. Latest release version is &bv%latestVersion%&7. &8(&7You're running &bv%currentVersion%&8)");
- if (main.messagesCfg.getBoolean("other.update-notice.send-in-console", true))
- updateResult.forEach(Utils.logger::warning);
+ updateResult = Utils.replaceAllInList(updateResult, "%currentVersion%", currentVersion);
+ updateResult = Utils.replaceAllInList(updateResult, "%latestVersion%", latestVersion);
+ updateResult = Utils.colorizeAllInList(updateResult);
- // notify any players that may be online already
- if (main.messagesCfg.getBoolean("other.update-notice.send-on-join", true)) {
- Bukkit.getOnlinePlayers().forEach(onlinePlayer -> {
- if (onlinePlayer.hasPermission("levelledmobs.receive-update-notifications")) {
- for (String msg : updateResult) {
- onlinePlayer.sendMessage(msg);
+ updateResult.forEach(Utils.logger::warning);
+ } else if (isOutOfDate) {
+
+ // for some reason config#getStringList doesn't allow defaults??
+ if (main.messagesCfg.contains("other.update-notice.messages")) {
+ updateResult = main.messagesCfg.getStringList("other.update-notice.messages");
+ } else {
+ updateResult = Arrays.asList(
+ "&b&nLevelledMobs Update Checker Notice:",
+ "&7Your &bLevelledMobs&7 version is &boutdated&7! Please update to" +
+ "&bv%latestVersion%&7 as soon as possible. &8(&7You''re running &bv%currentVersion%&8)");
+ }
+
+ updateResult = Utils.replaceAllInList(updateResult, "%currentVersion%", currentVersion);
+ updateResult = Utils.replaceAllInList(updateResult, "%latestVersion%", latestVersion);
+ updateResult = Utils.colorizeAllInList(updateResult);
+
+ if (main.messagesCfg.getBoolean("other.update-notice.send-in-console", true))
+ updateResult.forEach(Utils.logger::warning);
+
+ // notify any players that may be online already
+ if (main.messagesCfg.getBoolean("other.update-notice.send-on-join", true)) {
+ Bukkit.getOnlinePlayers().forEach(onlinePlayer -> {
+ if (onlinePlayer.hasPermission("levelledmobs.receive-update-notifications")) {
+ for (final String msg : updateResult) {
+ onlinePlayer.sendMessage(msg);
+ }
+ //updateResult.forEach(onlinePlayer::sendMessage); //compiler didn't like this :(
}
- //updateResult.forEach(onlinePlayer::sendMessage); //compiler didn't like this :(
- }
- });
+ });
+ }
}
- }
- });
+ });
+ }
+ catch (final OutdatedServerVersionException e){
+ e.printStackTrace();
+ }
}
}
@@ -400,4 +421,17 @@ public void removeRecentlyJoinedPlayer(final Player player){
recentlyJoinedPlayers.remove(player);
}
}
+
+ @Nullable
+ public Location getPlayerNetherPortalLocation(final @NotNull Player player){
+ synchronized (playerNetherPortals_Lock){
+ return playerNetherPortals.get(player);
+ }
+ }
+
+ public void setPlayerNetherPortalLocation(final @NotNull Player player, final @Nullable Location location){
+ synchronized (playerNetherPortals_Lock){
+ playerNetherPortals.put(player, location);
+ }
+ }
}
diff --git a/src/main/java/me/lokka30/levelledmobs/LevelledMobs.java b/src/main/java/me/lokka30/levelledmobs/LevelledMobs.java
index 1c46e14c4..47f13b4ce 100644
--- a/src/main/java/me/lokka30/levelledmobs/LevelledMobs.java
+++ b/src/main/java/me/lokka30/levelledmobs/LevelledMobs.java
@@ -4,6 +4,7 @@
package me.lokka30.levelledmobs;
+import me.lokka30.levelledmobs.commands.LevelledMobsCommand;
import me.lokka30.levelledmobs.customdrops.CustomDropsHandler;
import me.lokka30.levelledmobs.listeners.BlockPlaceListener;
import me.lokka30.levelledmobs.listeners.ChunkLoadListener;
@@ -13,13 +14,14 @@
import me.lokka30.levelledmobs.misc.*;
import me.lokka30.levelledmobs.rules.RulesManager;
import me.lokka30.levelledmobs.rules.RulesParsingManager;
-import me.lokka30.microlib.QuickTimer;
+import me.lokka30.microlib.maths.QuickTimer;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.HandlerList;
import org.bukkit.plugin.java.JavaPlugin;
+import org.jetbrains.annotations.NotNull;
import java.time.Instant;
import java.util.*;
@@ -30,17 +32,16 @@
* @author lokka30, stumper66
* @since 1.0
*/
-public class LevelledMobs extends JavaPlugin {
+public final class LevelledMobs extends JavaPlugin {
// Manager classes
public LevelInterface levelInterface;
public LevelManager levelManager;
public final MobDataManager mobDataManager = new MobDataManager(this);
- public WorldGuardIntegration worldGuardIntegration;
public CustomDropsHandler customDropsHandler;
- public ChunkLoadListener chunkLoadListener;
- public BlockPlaceListener blockPlaceListener;
- public PlayerInteractEventListener playerInteractEventListener;
+ ChunkLoadListener chunkLoadListener;
+ BlockPlaceListener blockPlaceListener;
+ PlayerInteractEventListener playerInteractEventListener;
public Namespaced_Keys namespaced_keys;
public final Companion companion = new Companion(this);
public final MobHeadManager mobHeadManager = new MobHeadManager(this);
@@ -50,6 +51,7 @@ public class LevelledMobs extends JavaPlugin {
public final NametagQueueManager nametagQueueManager_ = new NametagQueueManager(this);
public final NametagTimerChecker nametagTimerChecker = new NametagTimerChecker(this);
public final Object attributeSyncObject = new Object();
+ public LevelledMobsCommand levelledMobsCommand;
public Random random;
public PlaceholderApiIntegration placeholderApiIntegration;
public boolean migratedFromPre30;
@@ -66,24 +68,15 @@ public class LevelledMobs extends JavaPlugin {
// Misc
public Map> customMobGroups;
- public EntityDamageDebugListener entityDamageDebugListener;
+ EntityDamageDebugListener entityDamageDebugListener;
public int incompatibilitiesAmount;
private long loadTime;
public WeakHashMap playerLevellingEntities;
public Stack cacheCheck;
- @Override
- public void onLoad() {
- Utils.logger.info("&f~ Initiating start-up procedure ~");
- final QuickTimer timer = new QuickTimer(); // Record how long it takes for the plugin to load.
-
- companion.checkWorldGuard(); // Do not move this from onLoad. It will not work otherwise.
-
- loadTime = timer.getTimer(); // combine the load time with enable time.
- }
-
@Override
public void onEnable() {
+ Utils.logger.info("&f~ Initiating start-up procedure ~");
final QuickTimer timer = new QuickTimer();
this.namespaced_keys = new Namespaced_Keys(this);
@@ -114,7 +107,7 @@ public void onEnable() {
Utils.logger.info("&f~ Start-up complete, took &b" + loadTime + "ms&f ~");
}
- public void reloadLM(final CommandSender sender){
+ public void reloadLM(final @NotNull CommandSender sender){
migratedFromPre30 = false;
List reloadStartedMsg = messagesCfg.getStringList("command.levelledmobs.reload.started");
reloadStartedMsg = Utils.replaceAllInList(reloadStartedMsg, "%prefix%", configUtils.getPrefix());
diff --git a/src/main/java/me/lokka30/levelledmobs/commands/LevelledMobsCommand.java b/src/main/java/me/lokka30/levelledmobs/commands/LevelledMobsCommand.java
index 54d13c277..fc16f3df1 100644
--- a/src/main/java/me/lokka30/levelledmobs/commands/LevelledMobsCommand.java
+++ b/src/main/java/me/lokka30/levelledmobs/commands/LevelledMobsCommand.java
@@ -6,11 +6,14 @@
import me.lokka30.levelledmobs.LevelledMobs;
import me.lokka30.levelledmobs.commands.subcommands.*;
+import me.lokka30.levelledmobs.misc.PaperUtils;
import me.lokka30.levelledmobs.misc.Utils;
+import org.bukkit.Location;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
+import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
@@ -30,22 +33,29 @@ public class LevelledMobsCommand implements CommandExecutor, TabCompleter {
public LevelledMobsCommand(final LevelledMobs main) {
this.main = main;
+ compatibilitySubcommand = new CompatibilitySubcommand(main);
+ debugSubcommand = new DebugSubcommand(main);
+ infoSubcommand = new InfoSubcommand(main);
+ killSubcommand = new KillSubcommand(main);
spawnerSubCommand = new SpawnerSubCommand(main);
+ reloadSubcommand = new ReloadSubcommand();
rulesSubcommand = new RulesSubcommand(main);
+ spawnerEggCommand = new SpawnerEggCommand(main);
+ summonSubcommand = new SummonSubcommand(main);
}
// Retain alphabetical order please.
- private final CompatibilitySubcommand compatibilitySubcommand = new CompatibilitySubcommand();
- private final GenerateMobDataSubcommand generateMobDataSubcommand = new GenerateMobDataSubcommand();
- private final InfoSubcommand infoSubcommand = new InfoSubcommand();
- private final KillSubcommand killSubcommand = new KillSubcommand();
- private final ReloadSubcommand reloadSubcommand = new ReloadSubcommand();
+ private final CompatibilitySubcommand compatibilitySubcommand;
+ private final DebugSubcommand debugSubcommand;
+ private final InfoSubcommand infoSubcommand;
+ private final KillSubcommand killSubcommand;
+ private final ReloadSubcommand reloadSubcommand;
private final RulesSubcommand rulesSubcommand;
- private final SpawnerSubCommand spawnerSubCommand;
- private final SummonSubcommand summonSubcommand = new SummonSubcommand();
- private final DebugSubcommand debugSubcommand = new DebugSubcommand();
+ private final SpawnerEggCommand spawnerEggCommand;
+ public final SpawnerSubCommand spawnerSubCommand;
+ private final SummonSubcommand summonSubcommand;
- public boolean onCommand(@NotNull final CommandSender sender, final Command command, final String label, final String[] args) {
+ public boolean onCommand(@NotNull final CommandSender sender, final @NotNull Command command, final @NotNull String label, final String[] args) {
if (sender.hasPermission("levelledmobs.command")) {
if (args.length == 0) {
sendMainUsage(sender, label);
@@ -58,9 +68,6 @@ public boolean onCommand(@NotNull final CommandSender sender, final Command comm
case "debug":
debugSubcommand.parseSubcommand(main, sender, label, args);
break;
- case "generatemobdata":
- generateMobDataSubcommand.parseSubcommand(main, sender, label, args);
- break;
case "info":
infoSubcommand.parseSubcommand(main, sender, label, args);
break;
@@ -79,6 +86,9 @@ public boolean onCommand(@NotNull final CommandSender sender, final Command comm
case "summon":
summonSubcommand.parseSubcommand(main, sender, label, args);
break;
+ case "egg":
+ spawnerEggCommand.parseSubcommand(main, sender, label, args);
+ break;
default:
sendMainUsage(sender, label);
break;
@@ -99,12 +109,12 @@ private void sendMainUsage(@NotNull final CommandSender sender, final String lab
}
// Retain alphabetical order please.
- private final List commandsToCheck = Arrays.asList("debug", "summon", "kill", "reload", "info", "compatibility", "spawner", "rules");
+ private final List commandsToCheck = Arrays.asList("debug", "egg", "summon", "kill", "reload", "info", "compatibility", "spawner", "rules");
@Override
- public List onTabComplete(final CommandSender sender, final Command cmd, final String alias, @NotNull final String @NotNull [] args) {
+ public List onTabComplete(final @NotNull CommandSender sender, final @NotNull Command cmd, final @NotNull String alias, @NotNull final String @NotNull [] args) {
if (args.length == 1) {
- List suggestions = new LinkedList<>();
+ final List suggestions = new LinkedList<>();
commandsToCheck.forEach(command -> {
if (sender.hasPermission("levelledmobs.command." + command)) {
@@ -116,8 +126,6 @@ public List onTabComplete(final CommandSender sender, final Command cmd,
} else {
switch (args[0].toLowerCase()) {
// Retain alphabetical order please.
- case "generatemobdata":
- return generateMobDataSubcommand.parseTabCompletions(main, sender, args);
case "kill":
return killSubcommand.parseTabCompletions(main, sender, args);
case "rules":
@@ -126,6 +134,8 @@ public List onTabComplete(final CommandSender sender, final Command cmd,
return spawnerSubCommand.parseTabCompletions(main, sender, args);
case "summon":
return summonSubcommand.parseTabCompletions(main, sender, args);
+ case "egg":
+ return spawnerEggCommand.parseTabCompletions(main, sender, args);
// the missing subcommands don't have tab completions, don't bother including them.
default:
return Collections.emptyList();
diff --git a/src/main/java/me/lokka30/levelledmobs/commands/MessagesBase.java b/src/main/java/me/lokka30/levelledmobs/commands/MessagesBase.java
new file mode 100644
index 000000000..caf43ec74
--- /dev/null
+++ b/src/main/java/me/lokka30/levelledmobs/commands/MessagesBase.java
@@ -0,0 +1,101 @@
+package me.lokka30.levelledmobs.commands;
+
+import me.lokka30.levelledmobs.LevelledMobs;
+import me.lokka30.levelledmobs.misc.Utils;
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * Provides common functions for showing messages stored in messages.yml
+ * to the user
+ *
+ * @author stumper66
+ * @since 3.3.0
+ */
+public class MessagesBase {
+ public MessagesBase(final LevelledMobs main){
+ this.main = main;
+ }
+
+ protected final LevelledMobs main;
+ protected String messageLabel;
+ protected CommandSender commandSender;
+
+ protected void showMessage(final @NotNull String path){
+ if (commandSender == null)
+ throw new NullPointerException("CommandSender must be set before calling showMessage");
+
+ List messages = main.messagesCfg.getStringList(path);
+ messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
+ messages = Utils.replaceAllInList(messages, "%label%", messageLabel != null ? messageLabel : "");
+ messages = Utils.colorizeAllInList(messages);
+ messages.forEach(commandSender::sendMessage);
+ }
+
+ protected void showMessage(final @NotNull String path, final @NotNull CommandSender sender){
+ List messages = main.messagesCfg.getStringList(path);
+ messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
+ messages = Utils.replaceAllInList(messages, "%label%", messageLabel != null ? messageLabel : "");
+ messages = Utils.colorizeAllInList(messages);
+ messages.forEach(sender::sendMessage);
+ }
+
+ protected void showMessage(final @NotNull String path, final @NotNull String replaceWhat, final @NotNull String replaceWith){
+ showMessage(
+ path,
+ new String[] { replaceWhat },
+ new String[] { replaceWith }
+ );
+ }
+
+ protected void showMessage(final @NotNull String path, final String @NotNull [] replaceWhat, final String @NotNull [] replaceWith){
+ if (commandSender == null)
+ throw new NullPointerException("CommandSender must be set before calling showMessage");
+
+ final List messages = getMessage(path, replaceWhat, replaceWith);
+ messages.forEach(commandSender::sendMessage);
+ }
+
+ protected void showMessage(final @NotNull String path, final String @NotNull [] replaceWhat, final String @NotNull [] replaceWith, final @NotNull CommandSender sender){
+ final List messages = getMessage(path, replaceWhat, replaceWith);
+ messages.forEach(sender::sendMessage);
+ }
+
+ @NotNull
+ protected String getMessage(final @NotNull String path){
+ List messages = main.messagesCfg.getStringList(path);
+ messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
+ messages = Utils.replaceAllInList(messages, "%label%", messageLabel != null ? messageLabel : "");
+ messages = Utils.colorizeAllInList(messages);
+
+ if (messages.isEmpty()) return "";
+ if (messages.size() == 1) return messages.get(0);
+ else return String.join("\n", messages);
+ }
+
+ @NotNull
+ protected List getMessage(final @NotNull String path, final @NotNull String replaceWhat, final @NotNull String replaceWith){
+ return getMessage(
+ path,
+ new String[]{ replaceWhat },
+ new String[]{ replaceWith }
+ );
+ }
+ @NotNull
+ protected List getMessage(final @NotNull String path, final String @NotNull [] replaceWhat, final String @NotNull [] replaceWith){
+ if (replaceWhat.length != replaceWith.length)
+ throw new ArrayIndexOutOfBoundsException("replaceWhat must be the same size as replaceWith");
+
+ List messages = main.messagesCfg.getStringList(path);
+ messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
+ messages = Utils.replaceAllInList(messages, "%label%", messageLabel != null ? messageLabel : "");
+
+ for (int i = 0; i < replaceWhat.length; i++)
+ messages = Utils.replaceAllInList(messages, replaceWhat[i], replaceWith[i]);
+
+ messages = Utils.colorizeAllInList(messages);
+ return messages;
+ }
+}
diff --git a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/CompatibilitySubcommand.java b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/CompatibilitySubcommand.java
index 97e50a229..bf0b3da8b 100644
--- a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/CompatibilitySubcommand.java
+++ b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/CompatibilitySubcommand.java
@@ -5,7 +5,7 @@
package me.lokka30.levelledmobs.commands.subcommands;
import me.lokka30.levelledmobs.LevelledMobs;
-import me.lokka30.levelledmobs.misc.Utils;
+import me.lokka30.levelledmobs.commands.MessagesBase;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
@@ -18,27 +18,27 @@
* @author lokka30
* @since 2.4.0
*/
-public class CompatibilitySubcommand implements Subcommand {
+public class CompatibilitySubcommand extends MessagesBase implements Subcommand {
+ public CompatibilitySubcommand(final LevelledMobs main){
+ super(main);
+ }
@Override
public void parseSubcommand(final LevelledMobs main, @NotNull final CommandSender sender, final String label, final String[] args) {
- if (sender.hasPermission("levelledmobs.command.compatibility")) {
- if (args.length == 1) {
- List messages = main.messagesCfg.getStringList("command.levelledmobs.compatibility.notice");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
- main.companion.checkCompatibility();
- } else {
- List messages = main.messagesCfg.getStringList("command.levelledmobs.compatibility.usage");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
- }
- } else {
+ commandSender = sender;
+ messageLabel = label;
+
+ if (!sender.hasPermission("levelledmobs.command.compatibility")) {
main.configUtils.sendNoPermissionMsg(sender);
+ return;
+ }
+
+ if (args.length == 1) {
+ showMessage("command.levelledmobs.compatibility.notice");
+ main.companion.checkCompatibility();
}
+ else
+ showMessage("command.levelledmobs.compatibility.usage");
}
@Override
diff --git a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/DebugSubcommand.java b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/DebugSubcommand.java
index dcfb160e2..4b3ce14ce 100644
--- a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/DebugSubcommand.java
+++ b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/DebugSubcommand.java
@@ -1,18 +1,24 @@
package me.lokka30.levelledmobs.commands.subcommands;
import me.lokka30.levelledmobs.LevelledMobs;
+import me.lokka30.levelledmobs.commands.MessagesBase;
import me.lokka30.levelledmobs.misc.DebugCreator;
-import me.lokka30.microlib.MessageUtils;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
-public class DebugSubcommand implements Subcommand {
+public class DebugSubcommand extends MessagesBase implements Subcommand {
+ public DebugSubcommand(final LevelledMobs main) {
+ super(main);
+ }
@Override
public void parseSubcommand(final LevelledMobs main, final @NotNull CommandSender sender, final String label, final String[] args) {
+ commandSender = sender;
+ messageLabel = label;
+
if (!sender.hasPermission("levelledmobs.command.debug")) {
main.configUtils.sendNoPermissionMsg(sender);
return;
@@ -20,20 +26,8 @@ public void parseSubcommand(final LevelledMobs main, final @NotNull CommandSende
if (args.length == 3 && "create".equalsIgnoreCase(args[1]) && "confirm".equalsIgnoreCase(args[2]))
DebugCreator.createDebug(main, sender);
- else{
- sender.sendMessage(MessageUtils.colorizeAll("&b&nCreate a Debugging ZIP\n" +
- "&7You should only run this command if a LevelledMobs developer has asked you to. It is used to assist users who are experiencing issues with the plugin.\n" +
- "&r\n" +
- "&7This command will generate a ZIP file containing the following required data:\n" +
- "&8 &m->&b Plugins list\n" +
- "&8 &m->&b Server version\n" +
- "&8 &m->&b Current and maximum online player count\n" +
- "&8 &m->&b The latest.log file&7 &8(/logs/latest.log)\n" +
- "&r\n" +
- "&7LevelledMobs developers will not redistribute or retain the data beyond the purpose of resolving any issue you may be experiencing. You may also verify the contents prior to sending the file.\n" +
- "&7To proceed in creating the ZIP file, please run:\n" +
- "&b/lm debug create confirm&7"));
- }
+ else
+ showMessage("other.create-debug");
}
@Override
diff --git a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/GenerateMobDataSubcommand.java b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/GenerateMobDataSubcommand.java
deleted file mode 100644
index 75c982746..000000000
--- a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/GenerateMobDataSubcommand.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2020-2021 lokka30. Use of this source code is governed by the GNU AGPL v3.0 license that can be found in the LICENSE.md file.
- */
-
-package me.lokka30.levelledmobs.commands.subcommands;
-
-import me.lokka30.levelledmobs.LevelledMobs;
-import me.lokka30.levelledmobs.misc.Utils;
-import me.lokka30.microlib.MessageUtils;
-import me.lokka30.microlib.QuickTimer;
-import org.bukkit.Bukkit;
-import org.bukkit.Location;
-import org.bukkit.World;
-import org.bukkit.attribute.Attribute;
-import org.bukkit.command.CommandSender;
-import org.bukkit.command.ConsoleCommandSender;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.EntityType;
-import org.bukkit.entity.LivingEntity;
-import org.jetbrains.annotations.NotNull;
-
-import java.io.File;
-import java.io.IOException;
-import java.text.SimpleDateFormat;
-import java.util.*;
-
-/**
- * This subcommand is considered dangerous as it spawns in all types of 'living entities' on the first loaded world at coordinates (0, 512, 0). It also freezes the server for a moment.
- *
- * @author lokka30
- * @since 2.4.0
- */
-public class GenerateMobDataSubcommand implements Subcommand {
-
- // Password for this command: ThisMightDestroyMyWorldIUnderstand
-
- private int attempts = 3;
- private boolean acknowledged = false;
-
- public final HashSet excludedEntityTypes = new HashSet<>(Arrays.asList("UNKNOWN", "PLAYER", "NPC", "ARMOR_STAND"));
-
- @Override
- public void parseSubcommand(final LevelledMobs main, final CommandSender sender, final String label, final String[] args) {
- if (!(sender instanceof ConsoleCommandSender)) {
- sender.sendMessage(MessageUtils.colorizeAll(main.configUtils.getPrefix() + " Only console may use this command."));
- return;
- }
-
- if (args.length != 2) {
- sender.sendMessage(MessageUtils.colorizeAll(main.configUtils.getPrefix() + " Usage: &b/" + label + " generateMobData "));
- return;
- }
-
- if (attempts == 0) {
- sender.sendMessage(MessageUtils.colorizeAll(main.configUtils.getPrefix() + " You have ran out of attempts to use the correct password. You will gain another 3 attempts next time you restart the server."));
- return;
- }
-
- // This is the password I also use for all my accounts. You won't use it.. right?
- if (!args[1].equals("ThisMightDestroyMyWorldIUnderstand")) {
- sender.sendMessage(MessageUtils.colorizeAll(main.configUtils.getPrefix() + " Invalid password '&b%password%&7'! You have &b" + attempts + "&7 more attempt(s) before this command is locked until next restart.").replace("%password%", args[1]));
- attempts--;
- return;
- }
-
- if (acknowledged) {
- sender.sendMessage(MessageUtils.colorizeAll(main.configUtils.getPrefix() + " Starting generateMobData..."));
- try {
- generateMobData(main);
- } catch (IOException ex) {
- sender.sendMessage(MessageUtils.colorizeAll(main.configUtils.getPrefix() + " Unable to generate mob data! Stack trace:"));
- ex.printStackTrace();
- }
- } else {
- acknowledged = true;
- sender.sendMessage(MessageUtils.colorizeAll(main.configUtils.getPrefix() + " &8&m**********&r &c&lWARNING!&r &8&m**********&r"));
- sender.sendMessage(MessageUtils.colorizeAll(main.configUtils.getPrefix() + " &fThis command can possibly cause significant issues on your server&7, especially by unexpected behaviour from other plugins."));
- sender.sendMessage(MessageUtils.colorizeAll(main.configUtils.getPrefix() + " &fIf you are sure &7you are meant to be running this command, please &frun this command again (with the password too)&7."));
- sender.sendMessage(MessageUtils.colorizeAll(main.configUtils.getPrefix() + " &fDevelopers are NOT responsible for any damages&7 that this plugin could unintentionally cause."));
- sender.sendMessage(MessageUtils.colorizeAll(main.configUtils.getPrefix() + " The files generated will still be&f reset next startup&7, and the files you will generate will &fnot take effect&7. This simply generates new ones which you should copy before you restart the server next."));
- sender.sendMessage(MessageUtils.colorizeAll(main.configUtils.getPrefix() + " &8(This acknowledgement notice will only appear once per restart.)"));
- }
- }
-
- @Override
- public List parseTabCompletions(final LevelledMobs main, final CommandSender sender, @NotNull final String[] args) {
- if (args.length == 2 && sender instanceof ConsoleCommandSender)
- return Collections.singletonList("(password?)");
-
- return Collections.emptyList();
- }
-
- YamlConfiguration dropsConfig;
-
- private void generateMobData(@NotNull final LevelledMobs main) throws IOException {
- final QuickTimer quickTimer = new QuickTimer();
-
- final File attribFile = new File(main.getDataFolder(), "defaultAttributes.yml");
- if (attribFile.exists()) attribFile.delete();
- attribFile.createNewFile();
- YamlConfiguration attribConfig = YamlConfiguration.loadConfiguration(attribFile);
- attribConfig.options().header("This is NOT a configuration file! All changes to this file will not take effect and be reset!");
-
- attribConfig.set("GENERATION_INFO.date", new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(new Date()) + ", Time" +
- "zone: " + Calendar.getInstance().getTimeZone().getDisplayName());
- attribConfig.set("GENERATION_INFO.server-version", Bukkit.getVersion());
-
- final World world = Bukkit.getWorlds().get(0);
-
- int entitiesSkipped = 0;
- int entitiesCompleted = 0;
-
- for (final EntityType entityType : EntityType.values()) {
-
- Utils.logger.info("&f&lGenerateMobData: &7Processing &b" + entityType + "&7:");
-
- /* Don't spawn certain entities. */
- if (excludedEntityTypes.contains(entityType.toString())) {
- Utils.logger.info("&f&lGenerateMobData: &7Skipping &b" + entityType + "&7.");
- entitiesSkipped++;
- continue;
- }
-
- /* Check if the mob is a LivingEntity, otherwise it isn't levellable at all, so no point in saving its attributes ;) */
- if (entityType.getEntityClass() == null) {
- Utils.logger.info("&f&lGenerateMobData: &8[&3" + entityType + "&8] &7Entity class is null, skipping.");
- entitiesSkipped++;
- continue;
- }
-
- Entity entity;
- try {
- entity = world.spawnEntity(new Location(world, 0, 512, 0), entityType);
- } catch (IllegalArgumentException ex) {
- Utils.logger.info("&f&lGenerateMobData: &8[&3" + entityType + "&8] &7This entity is not spawnable, skipping.");
- entitiesSkipped++;
- continue;
- }
-
- if (!(entity instanceof LivingEntity)) {
- Utils.logger.info("&f&lGenerateMobData: &8[&3" + entityType + "&8] &7Entity is not a LivingEntity, skipping...");
- entitiesSkipped++;
- continue;
- }
-
- Utils.logger.info("&f&lGenerateMobData: &8[&3" + entityType + "&8] &7Entity is a LivingEntity. Saving...");
-
- final LivingEntity livingEntity = (LivingEntity) entity;
-
- for (final Attribute attribute : Attribute.values()) {
- if (livingEntity.getAttribute(attribute) != null) {
- Utils.logger.info("&f&lGenerateMobData: &8[&3" + entityType + "&8] &7Saving attribute &b" + attribute + "&7...");
- attribConfig.set(entityType + "." + attribute, Objects.requireNonNull(livingEntity.getAttribute(attribute)).getBaseValue());
- }
- }
- Utils.logger.info("&f&lGenerateMobData: &8[&3" + entityType + "&8] &7Entity's attributes have been gathered.");
-
- entity.remove();
- entitiesCompleted++;
- Utils.logger.info("&f&lGenerateMobData: &8[&3" + entityType + "&8] &7Entity removed. Proceeding with next entity if it exists.");
- }
-
- attribConfig.save(attribFile);
- Utils.logger.info("&f&lGenerateMobData: &7Process completed. &8//&7 Processed &b" + (entitiesCompleted + entitiesSkipped) + "&7 entit" +
- "ies in &b" + quickTimer.getTimer() + "ms&7, where &b" + entitiesCompleted + "&7 entities had their attributes saved, a" +
- "nd &b" + entitiesSkipped + "&7 entities were skipped.");
- }
-}
diff --git a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/InfoSubcommand.java b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/InfoSubcommand.java
index 74d9ceed1..a6816a6c9 100644
--- a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/InfoSubcommand.java
+++ b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/InfoSubcommand.java
@@ -5,11 +5,11 @@
package me.lokka30.levelledmobs.commands.subcommands;
import me.lokka30.levelledmobs.LevelledMobs;
+import me.lokka30.levelledmobs.commands.MessagesBase;
import me.lokka30.levelledmobs.misc.Utils;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -20,10 +20,16 @@
* @author lokka30
* @since v2.0.0
*/
-public class InfoSubcommand implements Subcommand {
+public class InfoSubcommand extends MessagesBase implements Subcommand {
+ public InfoSubcommand(final LevelledMobs main){
+ super(main);
+ }
@Override
public void parseSubcommand(final LevelledMobs main, @NotNull final CommandSender sender, final String label, final String[] args) {
+ commandSender = sender;
+ messageLabel = label;
+
if (!sender.hasPermission("levelledmobs.command.info")) {
main.configUtils.sendNoPermissionMsg(sender);
return;
@@ -34,24 +40,17 @@ public void parseSubcommand(final LevelledMobs main, @NotNull final CommandSende
final String description = main.getDescription().getDescription();
assert description != null;
final List supportedVersions = Utils.getSupportedServerVersions();
- final List codeContributors = Arrays.asList("stumper66", "Eyrian", "iCodinqs", "deiphiz", "CoolBoy", "Esophose",
- "7smile7", "UltimaOath", "konsolas", "Shevchik", "Hugo5551", "limzikiki", "bStats Project", "SpigotMC Project");
+ final List codeContributors = List.of("stumper66", "Eyrian", "iCodinqs", "deiphiz", "CoolBoy", "Esophose",
+ "7smile7", "UltimaOath", "konsolas", "Shevchik", "Hugo5551", "limzikiki", "bStats Project", "SpigotMC Project", "ProfliX");
final String listSeparator = Objects.requireNonNull(main.messagesCfg.getString("command.levelledmobs.info.listSeparator"), "messages.yml: command.levelledmobs.info.listSeparator is undefined");
- List aboutMsg = main.messagesCfg.getStringList("command.levelledmobs.info.about");
- aboutMsg = Utils.replaceAllInList(aboutMsg, "%version%", version);
- aboutMsg = Utils.replaceAllInList(aboutMsg, "%description%", description);
- aboutMsg = Utils.replaceAllInList(aboutMsg, "%supportedVersions%", String.join(listSeparator, supportedVersions));
- aboutMsg = Utils.replaceAllInList(aboutMsg, "%contributors%", String.join(listSeparator, codeContributors));
- aboutMsg = Utils.colorizeAllInList(aboutMsg);
- aboutMsg.forEach(sender::sendMessage);
- } else {
- List usageMsg = main.messagesCfg.getStringList("command.levelledmobs.info.usage");
- usageMsg = Utils.replaceAllInList(usageMsg, "%prefix%", main.configUtils.getPrefix());
- usageMsg = Utils.replaceAllInList(usageMsg, "%label%", label);
- usageMsg = Utils.colorizeAllInList(usageMsg);
- usageMsg.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.info.about",
+ new String[]{ "%version%", "%description%", "%supportedVersions%", "%contributors%"},
+ new String[]{ version, description, String.join(listSeparator, supportedVersions), String.join(listSeparator, codeContributors) }
+ );
}
+ else
+ showMessage("command.levelledmobs.info.usage");
}
@Override
diff --git a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/KillSubcommand.java b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/KillSubcommand.java
index ae3b4ae4b..d59a59905 100644
--- a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/KillSubcommand.java
+++ b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/KillSubcommand.java
@@ -5,6 +5,7 @@
package me.lokka30.levelledmobs.commands.subcommands;
import me.lokka30.levelledmobs.LevelledMobs;
+import me.lokka30.levelledmobs.commands.MessagesBase;
import me.lokka30.levelledmobs.misc.RequestedLevel;
import me.lokka30.levelledmobs.misc.Utils;
import org.bukkit.Bukkit;
@@ -26,17 +27,23 @@
* @author stumper66
* @since 2.0
*/
-public class KillSubcommand implements Subcommand {
+public class KillSubcommand extends MessagesBase implements Subcommand {
+ public KillSubcommand(final LevelledMobs main){
+ super(main);
+ }
@Override
public void parseSubcommand(final LevelledMobs main, final @NotNull CommandSender sender, final String label, final String[] args) {
+ commandSender = sender;
+ messageLabel = label;
+
if (!sender.hasPermission("levelledmobs.command.kill")) {
main.configUtils.sendNoPermissionMsg(sender);
return;
}
if (args.length <= 1) {
- sendUsageMsg(sender, label, main);
+ showMessage("command.levelledmobs.kill.usage");
return;
}
@@ -65,42 +72,32 @@ public void parseSubcommand(final LevelledMobs main, final @NotNull CommandSende
if (checkArgs == 2) {
if (sender instanceof Player) {
final Player player = (Player) sender;
- parseKillAll(sender, Collections.singletonList(player.getWorld()), main, useNoDrops, rl);
- } else {
- List messages = main.messagesCfg.getStringList("command.levelledmobs.kill.all.usage-console");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
+ parseKillAll(Collections.singletonList(player.getWorld()), main, useNoDrops, rl);
}
+ else
+ showMessage("command.levelledmobs.kill.all.usage-console");
+
} else if (checkArgs == 3 || checkArgs == 4) {
if (args[2].equals("*")) {
- parseKillAll(sender, Bukkit.getWorlds(), main, useNoDrops, rl);
+ parseKillAll(Bukkit.getWorlds(), main, useNoDrops, rl);
return;
}
if ("/nodrops".equalsIgnoreCase(args[2]))
- parseKillAll(sender, Bukkit.getWorlds(), main, true, rl);
+ parseKillAll(Bukkit.getWorlds(), main, true, rl);
else {
- World world = Bukkit.getWorld(args[2]);
+ final World world = Bukkit.getWorld(args[2]);
if (world == null) {
- List messages = main.messagesCfg.getStringList("command.levelledmobs.kill.all.invalid-world");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.colorizeAllInList(messages);
- messages = Utils.replaceAllInList(messages, "%world%", args[2]); //This is after the list is colourised to ensure that an input of a world name '&aGreen' will not be colourised.
- messages.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.kill.all.invalid-world", "%world%", args[2]);
+ // TODO: see if we still need to follow the instructions below
+ //messages = Utils.replaceAllInList(messages, "%world%", args[2]); //This is after the list is colourised to ensure that an input of a world name '&aGreen' will not be colourised.
return;
}
- parseKillAll(sender, Collections.singletonList(world), main, useNoDrops, rl);
+ parseKillAll(Collections.singletonList(world), main, useNoDrops, rl);
}
- } else {
- List messages = main.messagesCfg.getStringList("command.levelledmobs.kill.all.usage");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
}
-
+ else
+ showMessage("command.levelledmobs.kill.all.usage");
break;
case "near":
if (!sender.hasPermission("levelledmobs.command.kill.near")) {
@@ -110,45 +107,29 @@ public void parseSubcommand(final LevelledMobs main, final @NotNull CommandSende
if (checkArgs == 3 || checkArgs == 4) {
if (!(sender instanceof BlockCommandSender) && !(sender instanceof Player)) {
- List messages = main.messagesCfg.getStringList("common.players-only");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
+ showMessage("common.players-only");
return;
}
int radius;
try {
radius = Integer.parseInt(args[2]);
- } catch (NumberFormatException exception) {
- List messages = main.messagesCfg.getStringList("command.levelledmobs.kill.near.invalid-radius");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.colorizeAllInList(messages);
- messages = Utils.replaceAllInList(messages, "%radius%", args[2]); //After the list is colourised, so %radius% is not coloursied.
- messages.forEach(sender::sendMessage);
+ } catch (final NumberFormatException exception) {
+ showMessage("command.levelledmobs.kill.near.invalid-radius", "%radius%", args[2]);
+ //messages = Utils.replaceAllInList(messages, "%radius%", args[2]); //After the list is colourised, so %radius% is not coloursied.
return;
}
- int maxRadius = 1000;
+ final int maxRadius = 1000;
if (radius > maxRadius) {
radius = maxRadius;
-
- List messages = main.messagesCfg.getStringList("command.levelledmobs.kill.near.invalid-radius-max");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%maxRadius%", maxRadius + "");
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.kill.near.invalid-radius-max", "%maxRadius%", String.valueOf(maxRadius));
}
- int minRadius = 1;
+ final int minRadius = 1;
if (radius < minRadius) {
radius = minRadius;
-
- List messages = main.messagesCfg.getStringList("command.levelledmobs.kill.near.invalid-radius-min");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%minRadius%", minRadius + "");
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.kill.near.invalid-radius-min", "%minRadius%", String.valueOf(minRadius));
}
int killed = 0;
@@ -179,29 +160,22 @@ public void parseSubcommand(final LevelledMobs main, final @NotNull CommandSende
}
}
- List messages = main.messagesCfg.getStringList("command.levelledmobs.kill.near.success");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%killed%", killed + "");
- messages = Utils.replaceAllInList(messages, "%skipped%", skipped + "");
- messages = Utils.replaceAllInList(messages, "%radius%", radius + "");
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
- } else {
- List messages = main.messagesCfg.getStringList("command.levelledmobs.kill.near.usage");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.kill.near.success",
+ new String[]{ "%killed%", "%skipped%", "%radius%" },
+ new String[]{String.valueOf(killed), String.valueOf(skipped), String.valueOf(radius)}
+ );
}
+ else
+ showMessage("command.levelledmobs.kill.near.usage");
break;
default:
- sendUsageMsg(sender, label, main);
+ showMessage("command.levelledmobs.kill.usage");
}
}
@Nullable
- private RequestedLevel getLevelFromCommand(final @NotNull CommandSender sender, final String[] args){
+ private RequestedLevel getLevelFromCommand(final @NotNull CommandSender sender, final String @NotNull [] args){
int rangeSpecifiedFlag = -1;
for (int i = 0; i < args.length; i++) {
@@ -237,8 +211,7 @@ public List parseTabCompletions(final LevelledMobs main, final @NotNull
boolean containsNoDrops = false;
boolean containsLevels = false;
- StringBuilder sb = new StringBuilder();
- for (String arg : args) {
+ for (final String arg : args) {
if ("/nodrops".equalsIgnoreCase(arg))
containsNoDrops = true;
else if ("/levels".equalsIgnoreCase(arg))
@@ -251,12 +224,12 @@ else if ("/levels".equalsIgnoreCase(arg))
if (args[1].equalsIgnoreCase("all") && (args.length == 3 || args.length == 4)) {
if (sender.hasPermission("levelledmobs.command.kill.all")) {
- List worlds = new LinkedList<>();
+ final List worlds = new LinkedList<>();
if (!containsNoDrops) worlds.add("/nodrops");
if (!containsLevels) worlds.add("/levels");
if (args.length == 3 ) {
- for (World world : Bukkit.getWorlds()) {
+ for (final World world : Bukkit.getWorlds()) {
worlds.add("*");
if (main.rulesManager.getRule_IsWorldAllowedInAnyRule(world))
worlds.add(world.getName());
@@ -284,15 +257,7 @@ else if (args.length == 3)
return result;
}
- private void sendUsageMsg(final @NotNull CommandSender sender, final String label, final @NotNull LevelledMobs instance) {
- List messages = instance.messagesCfg.getStringList("command.levelledmobs.kill.usage");
- messages = Utils.replaceAllInList(messages, "%prefix%", instance.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
- }
-
- private void parseKillAll(final CommandSender sender, final @NotNull List worlds, final LevelledMobs main, final boolean useNoDrops, final RequestedLevel rl) {
+ private void parseKillAll(final @NotNull List worlds, final LevelledMobs main, final boolean useNoDrops, final RequestedLevel rl) {
int killed = 0;
int skipped = 0;
@@ -318,13 +283,10 @@ private void parseKillAll(final CommandSender sender, final @NotNull List
}
}
- List messages = main.messagesCfg.getStringList("command.levelledmobs.kill.all.success");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%killed%", killed + "");
- messages = Utils.replaceAllInList(messages, "%skipped%", skipped + "");
- messages = Utils.replaceAllInList(messages, "%worlds%", worlds.size() + "");
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.kill.all.success",
+ new String[]{ "%killed%", "%skipped%", "%worlds%"},
+ new String[]{String.valueOf(killed), String.valueOf(skipped), String.valueOf(worlds.size())}
+ );
}
private boolean skipKillingEntity(final LevelledMobs main, final @NotNull LivingEntity livingEntity, final RequestedLevel rl) {
diff --git a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/RulesSubcommand.java b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/RulesSubcommand.java
index 3dbba39d4..91fcaa7d1 100644
--- a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/RulesSubcommand.java
+++ b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/RulesSubcommand.java
@@ -5,17 +5,12 @@
package me.lokka30.levelledmobs.commands.subcommands;
import me.lokka30.levelledmobs.LevelledMobs;
+import me.lokka30.levelledmobs.commands.MessagesBase;
import me.lokka30.levelledmobs.managers.ExternalCompatibilityManager;
-import me.lokka30.levelledmobs.misc.CachedModalList;
-import me.lokka30.levelledmobs.misc.LivingEntityWrapper;
-import me.lokka30.levelledmobs.misc.QueueItem;
-import me.lokka30.levelledmobs.misc.Utils;
+import me.lokka30.levelledmobs.misc.*;
import me.lokka30.levelledmobs.rules.RuleInfo;
-import me.lokka30.microlib.MessageUtils;
-import net.md_5.bungee.api.chat.ClickEvent;
-import net.md_5.bungee.api.chat.HoverEvent;
-import net.md_5.bungee.api.chat.TextComponent;
-import net.md_5.bungee.api.chat.hover.content.Text;
+import me.lokka30.microlib.messaging.MessageUtils;
+import me.lokka30.microlib.other.VersionUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Particle;
@@ -45,23 +40,24 @@
* @author stumper66
* @since 3.0.0
*/
-public class RulesSubcommand implements Subcommand {
+public class RulesSubcommand extends MessagesBase implements Subcommand {
- public RulesSubcommand(final LevelledMobs main){
- this.main = main;
+ public RulesSubcommand(final LevelledMobs main) {
+ super(main);
}
- private final LevelledMobs main;
-
@Override
public void parseSubcommand(final LevelledMobs main, @NotNull final CommandSender sender, final String label, final String[] args) {
+ commandSender = sender;
+ messageLabel = label;
+
if (!sender.hasPermission("levelledmobs.command.rules")){
main.configUtils.sendNoPermissionMsg(sender);
return;
}
if (args.length == 1) {
- sender.sendMessage(MessageUtils.colorizeAll("&b&lLevelledMobs: &7Incomplete command"));
+ showMessage("command.levelledmobs.rules.incomplete-command");
return;
}
@@ -77,22 +73,21 @@ else if ("/near".equalsIgnoreCase(args[i]))
if ("show_all".equalsIgnoreCase(args[1])) {
if (sender instanceof Player)
- sender.sendMessage("Rules have been printed on the console");
+ showMessage("command.levelledmobs.rules.console-rules");
final StringBuilder sb = new StringBuilder();
- for (final String key : main.rulesParsingManager.rulePresets.keySet()) {
- final RuleInfo rpi = main.rulesParsingManager.rulePresets.get(key);
+ for (final RuleInfo rpi : main.rulesParsingManager.rulePresets.values()) {
sb.append("\n--------------------------------- Preset rule ----------------------------------\n");
- formatRulesVisually(rpi, sender, showOnConsole, Collections.singletonList("ruleIsEnabled"), sb);
+ sb.append(rpi.formatRulesVisually(List.of("ruleIsEnabled")));
}
sb.append("\n--------------------------------- Default values -------------------------------\n");
- formatRulesVisually(main.rulesParsingManager.defaultRule, sender, showOnConsole, null, sb);
+ sb.append(main.rulesParsingManager.defaultRule.formatRulesVisually());
for (final RuleInfo rpi : main.rulesParsingManager.customRules) {
sb.append("\n--------------------------------- Custom rule ----------------------------------\n");
- formatRulesVisually(rpi, sender, showOnConsole, null, sb);
+ sb.append(rpi.formatRulesVisually());
}
sb.append("\n--------------------------------------------------------------------------------------");
@@ -102,26 +97,30 @@ else if ("/near".equalsIgnoreCase(args[i]))
sender.sendMessage(sb.toString());
} else if ("show_effective".equalsIgnoreCase(args[1])) {
if (!(sender instanceof Player)) {
- sender.sendMessage("The command must be run by a player");
+ showMessage("common.no-player");
return;
}
getMobBeingLookedAt((Player) sender, showOnConsole, findNearbyEntities);
} else if ("show_rule".equalsIgnoreCase(args[1]))
showRule(sender, args);
- else if ("help_discord".equalsIgnoreCase(args[1]))
- showHyperlink(sender, "Click for Discord invite", "https://www.discord.io/arcaneplugins");
- else if ("help_wiki".equalsIgnoreCase(args[1]))
- showHyperlink(sender, "Click to open the wiki","https://github.com/lokka30/LevelledMobs/wiki");
+ else if ("help_discord".equalsIgnoreCase(args[1])) {
+ final String message = getMessage("command.levelledmobs.rules.discord-invite");
+ showHyperlink(sender, message, "https://www.discord.io/arcaneplugins");
+ }
+ else if ("help_wiki".equalsIgnoreCase(args[1])) {
+ final String message = getMessage("command.levelledmobs.rules.wiki-link");
+ showHyperlink(sender, message, "https://github.com/lokka30/LevelledMobs/wiki");
+ }
else if ("reset".equalsIgnoreCase(args[1]))
- resetRules(sender, label, args);
+ resetRules(sender, args);
else if ("force_all".equalsIgnoreCase(args[1]))
- forceRelevel(sender, label, args);
+ forceRelevel(sender);
else
- sender.sendMessage(MessageUtils.colorizeAll("&b&lLevelledMobs: &7Invalid command"));
+ showMessage("common.invalid-command");
}
- private void forceRelevel(final CommandSender sender, final String label, @NotNull final String[] args){
+ private void forceRelevel(final CommandSender sender){
int worldCount = 0;
int entityCount = 0;
@@ -147,18 +146,15 @@ private void forceRelevel(final CommandSender sender, final String label, @NotNu
}
}
- sender.sendMessage(MessageUtils.colorizeAll(String.format(
- "%s Rules Reprocessed for &b%s&7 mobs in &b%s&7 world(s)",
- label, entityCount, worldCount)));
+ showMessage("command.levelledmobs.rules.rules-reprocessed",
+ new String[]{ "%entitycount%", "%worldcount%" },
+ new String[]{String.valueOf(entityCount), String.valueOf(worldCount)}
+ );
}
- private void resetRules(final CommandSender sender, final String label, @NotNull final String @NotNull [] args){
- final String prefix = main.configUtils.getPrefix();
-
+ private void resetRules(final CommandSender sender, @NotNull final String @NotNull [] args){
if (args.length < 3 || args.length > 4){
- sender.sendMessage(prefix+ " Running this command will reset your rules to one of 3 defaults.\n" +
- "You must select if you want easy/normal/hard difficulty.\n" +
- "A backup will be made and your rules.yml reset to default");
+ showMessage("command.levelledmobs.rules.reset");
return;
}
@@ -172,22 +168,13 @@ private void resetRules(final CommandSender sender, final String label, @NotNull
break;
}
- if (difficulty.equals(ResetDifficulty.UNSPECIFIED)){
- sender.sendMessage(prefix+ " Invalid difficulty: " + args[2]);
+ if (difficulty == ResetDifficulty.UNSPECIFIED){
+ showMessage("command.levelledmobs.rules.invalid-difficulty", "%difficulty%", args[2]);
return;
}
if (args.length == 3){
- final StringBuilder sb = new StringBuilder();
- if (sender instanceof Player) sb.append("/");
- sb.append(label);
- for (final String arg : args) {
- sb.append(" ");
- sb.append(arg);
- }
-
- sender.sendMessage(prefix +" To reset your rules to " + args[2] + " difficulty, type in the following command:\n" +
- sb + " confirm");
+ showMessage("command.levelledmobs.rules.reset-syntax", "%difficulty%", args[2]);
return;
}
@@ -196,9 +183,9 @@ private void resetRules(final CommandSender sender, final String label, @NotNull
private void resetRules(final @NotNull CommandSender sender, final @NotNull ResetDifficulty difficulty){
final String prefix = main.configUtils.getPrefix();
- sender.sendMessage(prefix + " Resetting rules to " + difficulty);
+ showMessage("command.levelledmobs.rules.resetting", "%difficulty%", String.valueOf(difficulty));
- String filename;
+ final String filename;
switch (difficulty){
case EASY: filename = "predefined/rules_easy.yml";
@@ -210,7 +197,7 @@ private void resetRules(final @NotNull CommandSender sender, final @NotNull Rese
}
- try (InputStream stream = main.getResource(filename)) {
+ try (final InputStream stream = main.getResource(filename)) {
if (stream == null){
Utils.logger.error(prefix + " Input stream was null");
return;
@@ -226,12 +213,12 @@ private void resetRules(final @NotNull CommandSender sender, final @NotNull Rese
Files.copy(rulesFile.toPath(), rulesBackupFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
Files.copy(stream, rulesFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
- } catch (IOException ex) {
+ } catch (final IOException ex) {
ex.printStackTrace();
return;
}
- sender.sendMessage(prefix + " rules.yml updated successfully");
+ showMessage("command.levelledmobs.rules.reset-complete");
main.reloadLM(sender);
}
@@ -240,19 +227,20 @@ private enum ResetDifficulty{
}
private void showHyperlink(final CommandSender sender, final String message, final String url){
- if (sender instanceof Player) {
- final TextComponent component = new TextComponent(message);
- component.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url));
- component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(url)));
- final Player p = (Player) sender;
- p.spigot().sendMessage(component);
- } else
+ if (!(sender instanceof Player)){
sender.sendMessage(url);
+ return;
+ }
+
+ if (VersionUtils.isRunningPaper())
+ PaperUtils.sendHyperlink(sender, message, url);
+ else
+ SpigotUtils.sendHyperlink(sender, message, url);
}
private void showRule(final CommandSender sender, @NotNull final String @NotNull [] args){
if (args.length < 3){
- sender.sendMessage("Must specify a rule name.");
+ showMessage("command.levelledmobs.rules.rule-name-missing");
return;
}
@@ -263,7 +251,6 @@ private void showRule(final CommandSender sender, @NotNull final String @NotNull
for (final RuleInfo ruleInfo : main.rulesParsingManager.getAllRules())
allRuleNames.put(ruleInfo.getRuleName().replace(" ", "_"), ruleInfo);
- final String lastArg = args[args.length - 1];
String badRuleName = null;
for (int i = 2; i < args.length; i++){
@@ -281,20 +268,21 @@ else if (badRuleName == null)
}
if (badRuleName != null){
- sender.sendMessage("No rule was found with name " + badRuleName);
+ showMessage("command.levelledmobs.rules.rule-name-invalid", "%rulename%", badRuleName);
return;
}
if (foundRule == null){
- sender.sendMessage("Must specify a rule name");
+ showMessage("command.levelledmobs.rules.rule-name-missing");
return;
}
final RuleInfo rule = allRuleNames.get(foundRule);
final StringBuilder sb = new StringBuilder();
- sb.append(MessageUtils.colorizeAll("Showing all values for rule: &b" + rule.getRuleName() + "&r\n"));
+ sb.append(getMessage("command.levelledmobs.rules.showing-rules", "%rulename%", rule.getRuleName()));
+ sb.append("\n");
- formatRulesVisually(rule, sender, showOnConsole, Collections.singletonList("id"), sb);
+ sb.append(rule.formatRulesVisually(List.of("id")));
if (showOnConsole)
Utils.logger.info(sb.toString());
else
@@ -309,7 +297,7 @@ private void getMobBeingLookedAt(@NotNull final Player player, final boolean sho
for(final Entity entity : player.getNearbyEntities(10, 10, 10)){
if (!(entity instanceof LivingEntity)) continue;
- LivingEntity le = (LivingEntity) entity;
+ final LivingEntity le = (LivingEntity) entity;
if (findNearbyEntities) {
final double distance = le.getLocation().distanceSquared(player.getLocation());
entities.put(distance, le);
@@ -324,9 +312,9 @@ private void getMobBeingLookedAt(@NotNull final Player player, final boolean sho
}
if (!findNearbyEntities && livingEntity == null)
- player.sendMessage("Must be looking at a nearby entity");
+ showMessage("command.levelledmobs.rules.no-entities-visible");
else if (findNearbyEntities && entities.isEmpty())
- player.sendMessage("No entities were found within a 10 block radius");
+ showMessage("command.levelledmobs.rules.no-entities-near");
else {
if (findNearbyEntities)
livingEntity = entities.get(entities.firstKey());
@@ -337,18 +325,19 @@ else if (findNearbyEntities && entities.isEmpty())
String entityName = lmEntity.getTypeName();
if (ExternalCompatibilityManager.hasMythicMobsInstalled() && ExternalCompatibilityManager.isMythicMob(lmEntity))
entityName = ExternalCompatibilityManager.getMythicMobInternalName(lmEntity);
- // 0 1 2 3 4 5
- final String message = String.format("showing effective rules for: %s%s (%s) at location: %s, %s, %s",
- lmEntity.isLevelled() ? "level " + lmEntity.getMobLevel() + " " : "", // 0
- entityName, // 1
- lmEntity.getLivingEntity().getName(), // 2
- lmEntity.getLivingEntity().getLocation().getBlockX(), // 3
- lmEntity.getLivingEntity().getLocation().getBlockY(), // 4
- lmEntity.getLivingEntity().getLocation().getBlockZ() // 5
+
+ final String locationStr = String.format("%s, %s, %s",
+ lmEntity.getLivingEntity().getLocation().getBlockX(),
+ lmEntity.getLivingEntity().getLocation().getBlockY(),
+ lmEntity.getLivingEntity().getLocation().getBlockZ());
+ final List messages = getMessage("command.levelledmobs.rules.effective-rules",
+ new String[]{"%mobname%", "%entitytype%", "%location%"},
+ new String[]{ entityName, lmEntity.getNameIfBaby(), locationStr }
);
+
final StringBuilder sb = new StringBuilder();
- sb.append(message);
+ sb.append(String.join("\n", messages).replace(main.configUtils.getPrefix() + " ", ""));
player.sendMessage(sb.toString());
if (!showOnConsole) sb.setLength(0);
@@ -378,58 +367,13 @@ public void run() {
world.spawnParticle(Particle.SPELL, location, 20, 0, 0, 0, 0.1);
Thread.sleep(50);
}
- } catch (InterruptedException ignored) { }
+ } catch (final InterruptedException ignored) { }
}
};
runnable.runTaskAsynchronously(main);
}
-
- private void formatRulesVisually(@NotNull final RuleInfo pi, final CommandSender sender, final boolean showOnConsole, final List excludedKeys, final StringBuilder sb){
- final SortedMap values = new TreeMap<>();
-
- if (excludedKeys == null || !excludedKeys.contains("id")) {
- sb.append("id: ");
- sb.append(pi.getRuleName());
- sb.append("\n");
- }
-
- try {
- for(final Field f : pi.getClass().getDeclaredFields()) {
- if (!Modifier.isPublic(f.getModifiers())) continue;
- if (f.get(pi) == null) continue;
- if (f.getName().equals("ruleSourceNames")) continue;
- if (excludedKeys != null && excludedKeys.contains(f.getName())) continue;
- final Object value = f.get(pi);
- if (value.toString().equalsIgnoreCase("NOT_SPECIFIED")) continue;
- if (value.toString().equalsIgnoreCase("{}")) continue;
- if (value.toString().equalsIgnoreCase("[]")) continue;
- if (value.toString().equalsIgnoreCase("0") &&
- f.getName().equals("rulePriority")) continue;
- if (value.toString().equalsIgnoreCase("0.0")) continue;
- if (value.toString().equalsIgnoreCase("false") &&
- !f.getName().equals("ruleIsEnabled")) continue;
- if (value.toString().equalsIgnoreCase("NONE")) continue;
- if (value instanceof CachedModalList>) {
- CachedModalList> cml = (CachedModalList>) value;
- if (cml.isEmpty() && !cml.allowAll && !cml.excludeAll) continue;
- }
- final String showValue = "&b" + f.getName() + "&r, value: &b" + value + "&r";
- values.put(f.getName(), showValue);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- for (final String key : values.keySet()){
- sb.append(MessageUtils.colorizeAll(values.get(key)));
- sb.append("\n");
- }
-
- sb.setLength(sb.length() - 1); // remove trailing newline
- }
-
private void showEffectiveValues(final CommandSender sender, final @NotNull LivingEntityWrapper lmEntity, final boolean showOnConsole, final StringBuilder sb){
final SortedMap values = new TreeMap<>();
final List printedKeys = new LinkedList<>();
@@ -437,9 +381,9 @@ private void showEffectiveValues(final CommandSender sender, final @NotNull Livi
if (effectiveRules.isEmpty()){
if (showOnConsole)
- Utils.logger.info(sb + "\nNo effective rules were found");
+ Utils.logger.info(sb + "\n" + getMessage("command.levelledmobs.rules.no-effective-rules").replace(main.configUtils.getPrefix() + " ", ""));
else
- sender.sendMessage("No effective rules were found");
+ showMessage("command.levelledmobs.rules.no-effective-rules");
return;
}
@@ -470,7 +414,7 @@ private void showEffectiveValues(final CommandSender sender, final @NotNull Livi
printedKeys.add(f.getName());
}
}
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
}
@@ -478,8 +422,8 @@ private void showEffectiveValues(final CommandSender sender, final @NotNull Livi
sb.append(fineTuning);
sb.append("&r\n");
- for (final String key : values.keySet()){
- sb.append(values.get(key));
+ for (final String s : values.values()){
+ sb.append(s);
sb.append("&r\n");
}
@@ -526,8 +470,6 @@ else if (args.length >= 3) {
for (final RuleInfo ruleInfo : main.rulesParsingManager.getAllRules())
allRuleNames.add(ruleInfo.getRuleName().replace(" ", "_"));
- final String lastArg = args[args.length - 1];
-
for (int i = 2; i < args.length; i++) {
final String arg = args[i].toLowerCase();
diff --git a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SpawnerBaseClass.java b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SpawnerBaseClass.java
new file mode 100644
index 000000000..687e8fbf0
--- /dev/null
+++ b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SpawnerBaseClass.java
@@ -0,0 +1,218 @@
+package me.lokka30.levelledmobs.commands.subcommands;
+
+import me.lokka30.levelledmobs.LevelledMobs;
+import me.lokka30.levelledmobs.commands.MessagesBase;
+import me.lokka30.levelledmobs.misc.PaperUtils;
+import me.lokka30.levelledmobs.misc.SpigotUtils;
+import me.lokka30.levelledmobs.misc.Utils;
+import me.lokka30.levelledmobs.rules.DoNotMerge;
+import me.lokka30.microlib.messaging.MessageUtils;
+import me.lokka30.microlib.other.VersionUtils;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.persistence.PersistentDataType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+/**
+ * Provides common function between SpawnerSubCommand and SpawnerEggCommand
+ *
+ * @author stumper66
+ * @since 3.3.0
+ */
+public class SpawnerBaseClass extends MessagesBase {
+ SpawnerBaseClass(final LevelledMobs main){
+ super(main);
+ }
+
+ boolean hadInvalidArg;
+ int startingArgNum;
+
+ @Nullable
+ String getArgValue(final String key, final String @NotNull [] args, final boolean mustBeNumber){
+ int keyFlag = -1;
+ int nameStartFlag = - 1;
+ int nameEndFlag = - 1;
+
+ for (int i = startingArgNum; i < args.length; i++){
+ final String arg = args[i];
+ if (key.equalsIgnoreCase(arg))
+ keyFlag = i;
+ else if (keyFlag == i - 1 && arg.startsWith("\""))
+ nameStartFlag = i;
+ else if (nameStartFlag > -1 && !arg.startsWith("/") && arg.endsWith("\"")) {
+ nameEndFlag = i;
+ break;
+ }
+ }
+
+ if (keyFlag < 0) return null;
+ String keyValue;
+
+ if (nameEndFlag > 0) {
+ final StringBuilder sb = new StringBuilder();
+ for (int i = nameStartFlag; i <= nameEndFlag; i++) {
+ if (i > 0) sb.append(" ");
+ sb.append(args[i].trim());
+ }
+ keyValue = sb.toString().trim();
+ keyValue = keyValue.substring(1, keyValue.length() - 1);
+ }
+ else
+ keyValue = parseFlagValue(key, keyFlag, args, mustBeNumber);
+
+ return keyValue;
+ }
+
+ @Nullable
+ private String parseFlagValue(final String keyName, final int argNumber, final String @NotNull [] args, final boolean mustBeNumber){
+ if (argNumber + 1 >= args.length || args[argNumber + 1].startsWith("/")){
+ showMessage("command.levelledmobs.spawner.no-value", "%keyname%", keyName);
+ hadInvalidArg = true;
+ return null;
+ }
+
+ if (mustBeNumber && !Utils.isInteger(args[argNumber + 1])){
+ showMessage("command.levelledmobs.spawner.invalid-value", "%keyname%", keyName);
+ hadInvalidArg = true;
+ return null;
+ }
+
+ return args[argNumber + 1];
+ }
+
+ static void setMetaItems(final @Nullable ItemMeta meta, final @NotNull CustomSpawnerInfo info){
+ if (meta == null) return;
+
+ if (VersionUtils.isRunningPaper())
+ PaperUtils.updateItemDisplayName(meta, info.customName == null ? "LM Spawn Egg" : info.customName);
+ else
+ SpigotUtils.updateItemDisplayName(meta, info.customName == null ? "LM Spawn Egg" : info.customName);
+
+ List lore = new LinkedList<>();
+
+ try {
+ int itemsCount = 0;
+ final StringBuilder loreLine = new StringBuilder();
+ for (final Field f : info.getClass().getDeclaredFields()) {
+ if (!Modifier.isPublic(f.getModifiers())) continue;
+ if (f.get(info) == null) continue;
+ final String name = f.getName();
+ if (f.isAnnotationPresent(DoNotMerge.class)) continue;
+
+ if ("-1".equals(f.get(info).toString()) && (name.equals("minLevel") || name.equals("maxLevel")))
+ continue;
+
+ if (itemsCount > 2){
+ lore.add(loreLine.toString());
+ loreLine.setLength(0);
+ itemsCount = 0;
+ }
+
+ if (loreLine.length() > 0) loreLine.append(", ");
+ loreLine.append(String.format("&7%s: &b%s&7", name, f.get(info)));
+ itemsCount++;
+ }
+ if (itemsCount > 0)
+ lore.add(loreLine.toString());
+ }
+ catch (final Exception e){
+ e.printStackTrace();
+ }
+
+ if (!info.noLore && info.lore == null && info.customLore == null) {
+ lore = Utils.colorizeAllInList(lore);
+ if (VersionUtils.isRunningPaper())
+ PaperUtils.updateItemMetaLore(meta, lore);
+ else
+ SpigotUtils.updateItemMetaLore(meta, lore);
+
+ final StringBuilder sbLore = new StringBuilder();
+ for (final String loreLine : lore) {
+ if (sbLore.length() > 0) sbLore.append("\n");
+ sbLore.append(loreLine);
+ }
+ meta.getPersistentDataContainer().set(info.main.namespaced_keys.keySpawner_Lore, PersistentDataType.STRING, sbLore.toString());
+ }
+ else if (!info.noLore || info.customLore != null){
+ final String useLore = info.customLore == null ?
+ info.lore : MessageUtils.colorizeAll(info.customLore).replace("\\n", "\n");
+
+ lore.clear();
+ lore.addAll(List.of(useLore.split("\n")));
+ if (VersionUtils.isRunningPaper())
+ PaperUtils.updateItemMetaLore(meta, lore);
+ else
+ SpigotUtils.updateItemMetaLore(meta, lore);
+
+ meta.getPersistentDataContainer().set(info.main.namespaced_keys.keySpawner_Lore, PersistentDataType.STRING, useLore);
+ }
+ }
+
+ List checkTabCompletion(final List options, final String @NotNull [] args){
+ final Set commandsList = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+ commandsList.addAll(options);
+
+ boolean inQuotes = false;
+
+ for (int i = 1; i < args.length; i++) {
+ final String arg = args[i];
+
+ if (arg.startsWith("\"") && !arg.endsWith("\""))
+ inQuotes = true;
+ else if (inQuotes && arg.endsWith("\""))
+ inQuotes = false;
+
+ commandsList.remove(arg);
+ }
+
+ final String lastArg = args[args.length - 1];
+
+ if (inQuotes || lastArg.length() > 0 && lastArg.charAt(lastArg.length() - 1) == '\"')
+ return Collections.emptyList();
+
+ final List result = new ArrayList<>(commandsList.size());
+ result.addAll(commandsList);
+ return result;
+ }
+
+ public static class CustomSpawnerInfo{
+ public CustomSpawnerInfo(final LevelledMobs main, final String label){
+ this.main = main;
+ this.label = label;
+ this.minLevel = -1;
+ this.maxLevel = -1;
+ this.spawnType = EntityType.UNKNOWN;
+ }
+
+ @DoNotMerge
+ final public LevelledMobs main;
+ @DoNotMerge
+ final String label;
+ @DoNotMerge
+ public Player player;
+ public int minLevel;
+ public int maxLevel;
+ @DoNotMerge
+ boolean noLore;
+ public Integer delay;
+ public Integer maxNearbyEntities;
+ public Integer minSpawnDelay;
+ public Integer maxSpawnDelay;
+ public Integer requiredPlayerRange;
+ public Integer spawnCount;
+ public Integer spawnRange;
+ public String customDropId;
+ @DoNotMerge
+ public String customName;
+ public EntityType spawnType;
+ @DoNotMerge
+ String customLore;
+ public String lore;
+ }
+}
diff --git a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SpawnerEggCommand.java b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SpawnerEggCommand.java
new file mode 100644
index 000000000..621fe88d6
--- /dev/null
+++ b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SpawnerEggCommand.java
@@ -0,0 +1,227 @@
+package me.lokka30.levelledmobs.commands.subcommands;
+
+import me.lokka30.levelledmobs.LevelledMobs;
+import me.lokka30.levelledmobs.misc.PaperUtils;
+import me.lokka30.levelledmobs.misc.SpigotUtils;
+import me.lokka30.levelledmobs.misc.Utils;
+import me.lokka30.microlib.messaging.MessageUtils;
+import me.lokka30.microlib.other.VersionUtils;
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.persistence.PersistentDataType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+public class SpawnerEggCommand extends SpawnerBaseClass implements Subcommand {
+
+ public SpawnerEggCommand(final LevelledMobs main) {
+ super(main);
+ startingArgNum = 1;
+ }
+
+ final private List allEggOptions = Arrays.asList(
+ "/name", "/customdropid", "/entity", "/giveplayer", "/lore", "/minlevel", "/maxlevel", "/nolore");
+
+ @Override
+ public void parseSubcommand(final LevelledMobs main, @NotNull final CommandSender sender, final String label, final String[] args) {
+ commandSender = sender;
+ messageLabel = label;
+
+ if (!sender.hasPermission("levelledmobs.command.spawneregg")) {
+ main.configUtils.sendNoPermissionMsg(sender);
+ return;
+ }
+
+ if (!VersionUtils.isRunningPaper()){
+ showMessage("command.levelledmobs.spawn_egg.no-paper");
+ return;
+ }
+
+ if (args.length < 2){
+ showMessage("command.levelledmobs.spawn_egg.usage");
+ return;
+ }
+
+ boolean hasGivePlayer = false;
+ for (int i = 2; i < args.length; i++){
+ if ("/giveplayer".equalsIgnoreCase(args[i])){
+ hasGivePlayer = true;
+ break;
+ }
+ }
+
+ if (!hasGivePlayer && !(sender instanceof Player)){
+ showMessage("command.levelledmobs.spawn_egg.no-player");
+ return;
+ }
+
+ parseEggCommand(args);
+ }
+
+ private void parseEggCommand(final String[] args){
+ hadInvalidArg = false;
+
+ final SpawnerSubCommand.CustomSpawnerInfo info = new SpawnerSubCommand.CustomSpawnerInfo(main, messageLabel);
+ if (commandSender instanceof Player)
+ info.player = (Player) commandSender;
+
+ // arguments with no values go here:
+ for (int i = 1; i < args.length; i++) {
+ final String arg = args[i];
+ if ("/nolore".equalsIgnoreCase(arg)) {
+ info.noLore = true;
+ break;
+ }
+ }
+
+ for (int i = 0; i < allEggOptions.size() - 1; i++){
+ final boolean mustBeANumber = (i > 4);
+ final String command = allEggOptions.get(i);
+ final String foundValue = getArgValue(command, args, mustBeANumber);
+ if (hadInvalidArg) return;
+ if (Utils.isNullOrEmpty(foundValue)) continue;
+
+ switch (command){
+ case "/name": info.customName = foundValue; break;
+ case "/customdropid": info.customDropId = foundValue; break;
+ case "/lore": info.customLore = foundValue; break;
+ case "/entity":
+ try{
+ info.spawnType = EntityType.valueOf(foundValue.toUpperCase());
+ }
+ catch (final Exception ignored){
+ commandSender.sendMessage("Invalid spawn type: " + foundValue);
+ return;
+ }
+ break;
+ case "/minlevel": info.minLevel = Integer.parseInt(foundValue); break;
+ case "/maxlevel": info.maxLevel = Integer.parseInt(foundValue); break;
+ case "/giveplayer":
+ if (Utils.isNullOrEmpty(foundValue)){
+ showMessage("command.levelledmobs.spawn_egg.no-player-specified");
+ return;
+ }
+ try { info.player = Bukkit.getPlayer(foundValue); }
+ catch (final Exception e){
+ showMessage("common.player-offline", "%player%", foundValue);
+ return;
+ }
+ if (info.player == null){
+ showMessage("common.player-offline", "%player%", foundValue);
+ return;
+ }
+ break;
+ }
+ }
+
+ if (info.minLevel == -1 || info.maxLevel == -1 || info.spawnType == EntityType.UNKNOWN) {
+ showMessage("command.levelledmobs.spawn_egg.no-level-specified");
+ return;
+ }
+
+ if (info.player == null){
+ showMessage("command.levelledmobs.spawn_egg.no-player");
+ return;
+ }
+
+ generateEgg(info);
+ }
+
+ private void generateEgg(final @NotNull CustomSpawnerInfo info){
+ if (info.customName != null) info.customName = MessageUtils.colorizeAll(info.customName);
+
+ final String materialName = info.spawnType.name() + "_SPAWN_EGG";
+ final Material material = Material.getMaterial(materialName);
+ if (material == null){
+ // should never see this message:
+ commandSender.sendMessage("Invalid material: " + materialName);
+ return;
+ }
+ final ItemStack item = new ItemStack(material);
+ final ItemMeta meta = item.getItemMeta();
+ if (meta != null){
+ setMetaItems(meta, info);
+
+ meta.getPersistentDataContainer().set(info.main.namespaced_keys.spawnerEgg, PersistentDataType.INTEGER, 1);
+ meta.getPersistentDataContainer().set(info.main.namespaced_keys.keySpawner_MinLevel, PersistentDataType.INTEGER, info.minLevel);
+ meta.getPersistentDataContainer().set(info.main.namespaced_keys.keySpawner_MaxLevel, PersistentDataType.INTEGER, info.maxLevel);
+ if (!Utils.isNullOrEmpty(info.customDropId))
+ meta.getPersistentDataContainer().set(info.main.namespaced_keys.keySpawner_CustomDropId, PersistentDataType.STRING, info.customDropId);
+ if (info.spawnType != EntityType.UNKNOWN)
+ meta.getPersistentDataContainer().set(info.main.namespaced_keys.keySpawner_SpawnType, PersistentDataType.STRING, info.spawnType.toString());
+ if (info.customName != null)
+ meta.getPersistentDataContainer().set(info.main.namespaced_keys.keySpawner_CustomName, PersistentDataType.STRING, info.customName);
+
+ item.setItemMeta(meta);
+ }
+
+ int useInvSlotNum = info.player.getInventory().getHeldItemSlot();
+ if (info.player.getInventory().getItem(useInvSlotNum) != null)
+ useInvSlotNum = -1;
+
+ if (useInvSlotNum == -1) {
+ for (int i = 0; i <= 35; i++) {
+ if (info.player.getInventory().getItem(i) == null) {
+ useInvSlotNum = i;
+ break;
+ }
+ }
+ }
+
+ if (useInvSlotNum == -1){
+ showMessage("command.levelledmobs.spawner.inventory-full", info.player);
+ return;
+ }
+
+ info.player.getInventory().setItem(useInvSlotNum, item);
+
+ final String playerName = VersionUtils.isRunningPaper() ?
+ PaperUtils.getPlayerDisplayName(info.player) : SpigotUtils.getPlayerDisplayName(info.player);
+
+ final List message = getMessage("command.levelledmobs.spawn_egg.give-message-console",
+ new String[]{ "%minlevel%", "%maxlevel%", "%playername%", "%entitytype%" },
+ new String[]{String.valueOf(info.minLevel), String.valueOf(info.maxLevel), playerName, info.spawnType.name() }
+ );
+
+ if (!message.isEmpty()) {
+ final String consoleMsg = message.get(0).replace(main.configUtils.getPrefix() + " ", "&r");
+ Utils.logger.info(consoleMsg);
+ }
+
+ showMessage("command.levelledmobs.spawn_egg.give-message",
+ new String[]{ "%minlevel%", "%maxlevel%", "%playername%", "%entitytype%" },
+ new String[]{String.valueOf(info.minLevel), String.valueOf(info.maxLevel), playerName, info.spawnType.name() },
+ info.player
+ );
+ }
+
+ @Override
+ public List parseTabCompletions(final LevelledMobs main, final @NotNull CommandSender sender, @NotNull final String @NotNull [] args) {
+ if (!Utils.isNullOrEmpty(args[args.length - 2])) {
+ switch (args[args.length - 2].toLowerCase()){
+ case "/entity":
+ final List entityNames = new LinkedList<>();
+ for (final EntityType entityType : EntityType.values())
+ entityNames.add(entityType.toString().toLowerCase());
+
+ return entityNames;
+ case "/giveplayer":
+ final List players = new LinkedList<>();
+ for (final Player player : Bukkit.getOnlinePlayers())
+ players.add(player.getName());
+ players.sort(String.CASE_INSENSITIVE_ORDER);
+ return players;
+ }
+ }
+
+ return checkTabCompletion(allEggOptions, args);
+ }
+}
diff --git a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SpawnerSubCommand.java b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SpawnerSubCommand.java
index f099f555f..a840bd0ef 100644
--- a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SpawnerSubCommand.java
+++ b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SpawnerSubCommand.java
@@ -5,23 +5,21 @@
package me.lokka30.levelledmobs.commands.subcommands;
import me.lokka30.levelledmobs.LevelledMobs;
+import me.lokka30.levelledmobs.misc.PaperUtils;
+import me.lokka30.levelledmobs.misc.SpigotUtils;
import me.lokka30.levelledmobs.misc.Utils;
-import me.lokka30.levelledmobs.rules.DoNotMerge;
-import me.lokka30.microlib.MessageUtils;
+import me.lokka30.microlib.messaging.MessageUtils;
+import me.lokka30.microlib.other.VersionUtils;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
-import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
import java.util.*;
/**
@@ -31,31 +29,31 @@
* @author stumper66
* @since 3.0.0
*/
-public class SpawnerSubCommand implements Subcommand{
+public class SpawnerSubCommand extends SpawnerBaseClass implements Subcommand{
- public SpawnerSubCommand(final LevelledMobs main) {this.main = main;}
+ public SpawnerSubCommand(final LevelledMobs main) {
+ super(main);
+ startingArgNum = 2;
+ }
- final private LevelledMobs main;
final private List allSpawnerOptions = Arrays.asList(
"/name", "/customdropid", "/spawntype", "/giveplayer", "/lore", "/minlevel", "/maxlevel", "/delay",
"/maxnearbyentities", "/minspawndelay", "/maxspawndelay", "/requiredplayerrange",
"/spawncount", "/spawnrange", "/nolore"
);
- private boolean hadInvalidArg;
@Override
public void parseSubcommand(final LevelledMobs main, @NotNull final CommandSender sender, final String label, final String[] args) {
+ commandSender = sender;
+ messageLabel = label;
+
if (!sender.hasPermission("levelledmobs.command.spawner")) {
main.configUtils.sendNoPermissionMsg(sender);
return;
}
if (args.length < 2){
- List messages = main.messagesCfg.getStringList("command.levelledmobs.spawner.usage");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.spawner.usage");
return;
}
@@ -79,141 +77,91 @@ public void parseSubcommand(final LevelledMobs main, @NotNull final CommandSende
}
if ((!hasGivePlayer || operationEnum != OperationEnum.CREATE) && !(sender instanceof Player)){
- if (operationEnum == OperationEnum.CREATE)
- sender.sendMessage("Command can only be run by a player unless /giveplayer is specified");
- else
- sender.sendMessage("Command can only be run by a player");
+ final String messageName = operationEnum != OperationEnum.CREATE ?
+ "common.no-player" : "command.levelledmobs.spawner.no-player";
+
+ showMessage(messageName);
return;
}
switch (args[1].toLowerCase()){
case "create":
- parseCreateCommand(sender, label, args);
+ parseCreateCommand(args);
break;
case "copy":
- parseCopyCommand(sender, label, args);
+ parseCopyCommand(args);
break;
case "info":
- parseInfoCommand(sender, label, args);
+ parseInfoCommand(args);
break;
}
}
- private void parseInfoCommand(@NotNull final CommandSender sender, final String label, final String @NotNull [] args){
- final UUID playerId = ((Player) sender).getUniqueId();
+ private void parseInfoCommand(final String @NotNull [] args){
+ final UUID playerId = ((Player) commandSender).getUniqueId();
if (args.length == 2){
- List messages;
- if (main.companion.spawner_InfoIds.contains(playerId))
- messages = main.messagesCfg.getStringList("command.levelledmobs.spawner.info.status-enabled");
- else
- messages = main.messagesCfg.getStringList("command.levelledmobs.spawner.info.status-not-enabled");
-
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
+ showMessage(main.companion.spawner_InfoIds.contains(playerId) ?
+ "command.levelledmobs.spawner.info.status-enabled" : "command.levelledmobs.spawner.info.status-not-enabled");
return;
}
if ("on".equalsIgnoreCase(args[2])){
if (main.companion.spawner_CopyIds.contains(playerId)) {
// can't have both enabled. We'll disable copy first
- copyGotDisabled(sender, playerId, label);
+ copyGotDisabled(playerId);
}
main.companion.spawner_InfoIds.add(playerId);
- List messages = main.messagesCfg.getStringList("command.levelledmobs.spawner.info.enabled");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.spawner.info.enabled");
}
else if ("off".equalsIgnoreCase(args[2]))
- infoGotDisabled(sender, playerId, label);
-
- checkListener();
+ infoGotDisabled(playerId);
}
- private void parseCopyCommand(@NotNull final CommandSender sender, final String label, final String[] args){
- if (!sender.hasPermission("levelledmobs.command.spawner.copy")) {
- main.configUtils.sendNoPermissionMsg(sender);
+ private void parseCopyCommand(final String[] args){
+ if (!commandSender.hasPermission("levelledmobs.command.spawner.copy")) {
+ main.configUtils.sendNoPermissionMsg(commandSender);
return;
}
- final UUID playerId = ((Player) sender).getUniqueId();
+ final UUID playerId = ((Player) commandSender).getUniqueId();
if (args.length == 2){
- List messages;
- if (main.companion.spawner_CopyIds.contains(playerId))
- messages = main.messagesCfg.getStringList("command.levelledmobs.spawner.copy.status-enabled");
- else
- messages = main.messagesCfg.getStringList("command.levelledmobs.spawner.copy.status-not-enabled");
-
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
-
+ showMessage(main.companion.spawner_CopyIds.contains(playerId) ?
+ "command.levelledmobs.spawner.copy.status-enabled" : "command.levelledmobs.spawner.copy.status-not-enabled");
return;
}
if ("on".equalsIgnoreCase(args[2])){
if (main.companion.spawner_InfoIds.contains(playerId)) {
// can't have both enabled. We'll disable info first
- infoGotDisabled(sender, playerId, label);
+ infoGotDisabled(playerId);
}
main.companion.spawner_CopyIds.add(playerId);
- List messages = main.messagesCfg.getStringList("command.levelledmobs.spawner.copy.enabled");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.spawner.copy.enabled");
}
else if ("off".equalsIgnoreCase(args[2]))
- copyGotDisabled(sender, playerId, label);
-
- checkListener();
+ copyGotDisabled(playerId);
}
- private void copyGotDisabled(final @NotNull CommandSender sender, final UUID playerId, final String label){
+ private void copyGotDisabled(final UUID playerId){
main.companion.spawner_CopyIds.remove(playerId);
- List messages = main.messagesCfg.getStringList("command.levelledmobs.spawner.copy.disabled");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.spawner.copy.disabled");
}
- private void infoGotDisabled(final @NotNull CommandSender sender, final UUID playerId, final String label){
+ private void infoGotDisabled(final UUID playerId){
main.companion.spawner_InfoIds.remove(playerId);
- List messages = main.messagesCfg.getStringList("command.levelledmobs.spawner.info.disabled");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.spawner.info.disabled");
}
-
- private void checkListener(){
- final boolean needsListener = (!main.companion.spawner_InfoIds.isEmpty() || !main.companion.spawner_CopyIds.isEmpty());
- if (needsListener && !main.companion.playerInteractListenerIsRegistered){
- main.companion.playerInteractListenerIsRegistered = true;
- Bukkit.getPluginManager().registerEvents(main.playerInteractEventListener, main);
- }
- else if (!needsListener && main.companion.playerInteractListenerIsRegistered){
- main.companion.playerInteractListenerIsRegistered = false;
- HandlerList.unregisterAll(main.playerInteractEventListener);
- }
- }
-
- private void parseCreateCommand(@NotNull final CommandSender sender, final String label, final String[] args){
+ private void parseCreateCommand(final String[] args){
hadInvalidArg = false;
- final CustomSpawnerInfo info = new CustomSpawnerInfo(main, label);
- if (sender instanceof Player)
- info.player = (Player) sender;
+ final CustomSpawnerInfo info = new CustomSpawnerInfo(main, messageLabel);
+ if (commandSender instanceof Player)
+ info.player = (Player) commandSender;
// arguments with no values go here:
for (int i = 1; i < args.length; i++) {
@@ -227,7 +175,7 @@ private void parseCreateCommand(@NotNull final CommandSender sender, final Strin
for (int i = 0; i < allSpawnerOptions.size() - 1; i++){
final boolean mustBeANumber = (i > 4);
final String command = allSpawnerOptions.get(i);
- final String foundValue = getArgValue(command, args, sender, label, mustBeANumber);
+ final String foundValue = getArgValue(command, args, mustBeANumber);
if (hadInvalidArg) return;
if (Utils.isNullOrEmpty(foundValue)) continue;
@@ -239,8 +187,8 @@ private void parseCreateCommand(@NotNull final CommandSender sender, final Strin
try{
info.spawnType = EntityType.valueOf(foundValue.toUpperCase());
}
- catch (Exception ignored){
- sender.sendMessage("Invalid spawn type: " + foundValue);
+ catch (final Exception ignored){
+ commandSender.sendMessage("Invalid spawn type: " + foundValue);
return;
}
break;
@@ -255,16 +203,16 @@ private void parseCreateCommand(@NotNull final CommandSender sender, final Strin
case "/spawnrange": info.spawnRange = Integer.parseInt(foundValue); break;
case "/giveplayer":
if (Utils.isNullOrEmpty(foundValue)){
- sender.sendMessage("No player was specified");
+ showMessage("command.levelledmobs.spawner.no-player-specified");
return;
}
try { info.player = Bukkit.getPlayer(foundValue); }
- catch (Exception e){
- sender.sendMessage("Invalid or offline player: " + foundValue);
+ catch (final Exception e){
+ showMessage("common.player-offline", "%player%", foundValue);
return;
}
if (info.player == null){
- sender.sendMessage("Invalid or offline player: " + foundValue);
+ showMessage("common.player-offline", "%player%", foundValue);
return;
}
break;
@@ -272,159 +220,32 @@ private void parseCreateCommand(@NotNull final CommandSender sender, final Strin
}
if (info.minLevel == -1 && info.maxLevel == -1) {
- List messages = main.messagesCfg.getStringList("command.levelledmobs.spawner.no-level-specified");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.spawner.no-level-specified");
return;
}
if (info.player == null){
- sender.sendMessage("No player was specified");
+ showMessage("command.levelledmobs.spawner.no-player-specified");
return;
}
generateSpawner(info);
}
- @Nullable
- private String getArgValue(final String key, final String @NotNull [] args, final CommandSender sender, final String label, final boolean mustBeNumber){
- int keyFlag = -1;
- int nameStartFlag = - 1;
- int nameEndFlag = - 1;
-
- for (int i = 2; i < args.length; i++){
- final String arg = args[i];
- if (key.equalsIgnoreCase(arg))
- keyFlag = i;
- else if (keyFlag == i - 1 && arg.startsWith("\""))
- nameStartFlag = i;
- else if (nameStartFlag > -1 && !arg.startsWith("/") && arg.endsWith("\"")) {
- nameEndFlag = i;
- break;
- }
- }
-
- if (keyFlag < 0) return null;
- String keyValue;
-
- if (nameEndFlag > 0) {
- final StringBuilder sb = new StringBuilder();
- for (int i = nameStartFlag; i <= nameEndFlag; i++) {
- if (i > 0) sb.append(" ");
- sb.append(args[i].trim());
- }
- keyValue = sb.toString().trim();
- keyValue = keyValue.substring(1, keyValue.length() - 1);
- }
- else
- keyValue = parseFlagValue(sender, key, keyFlag, args, mustBeNumber, label);
-
- return keyValue;
- }
-
- private @Nullable String parseFlagValue(final CommandSender sender, final String keyName, final int argNumber, final String @NotNull [] args, final boolean mustBeNumber, final String label){
- if (argNumber + 1 >= args.length || args[argNumber + 1].startsWith("/")){
- List message = main.messagesCfg.getStringList("command.levelledmobs.spawner.no-value");
- message = Utils.replaceAllInList(message, "%prefix%", main.configUtils.getPrefix());
- message = Utils.replaceAllInList(message, "%label%", label);
- message = Utils.replaceAllInList(message, "%keyname%", keyName);
- message = Utils.colorizeAllInList(message);
- message.forEach(sender::sendMessage);
- hadInvalidArg = true;
- return null;
- }
-
- if (mustBeNumber && !Utils.isInteger(args[argNumber + 1])){
- List message = main.messagesCfg.getStringList("command.levelledmobs.spawner.invalid-value");
- message = Utils.replaceAllInList(message, "%prefix%", main.configUtils.getPrefix());
- message = Utils.replaceAllInList(message, "%label%", label);
- message = Utils.replaceAllInList(message, "%keyname%", keyName);
- message = Utils.colorizeAllInList(message);
- message.forEach(sender::sendMessage);
- hadInvalidArg = true;
- return null;
- }
-
- return args[argNumber + 1];
- }
-
- public static void generateSpawner(final @NotNull CustomSpawnerInfo info){
- if (info.maxSpawnDelay != null && (info.minSpawnDelay == null || info.minSpawnDelay > info.maxSpawnDelay)) {
- // settting max spawn delay lower than min spawn delay will result in an exception
- info.minSpawnDelay = info.maxSpawnDelay;
- }
-
- if (info.minSpawnDelay != null && (info.maxSpawnDelay == null || info.maxSpawnDelay > info.minSpawnDelay)) {
- // settting min spawn delay higher than max spawn delay will result in an exception
- info.maxSpawnDelay = info.minSpawnDelay;
- }
-
+ public void generateSpawner(final @NotNull CustomSpawnerInfo info){
if (info.customName != null) info.customName = MessageUtils.colorizeAll(info.customName);
final ItemStack item = new ItemStack(Material.SPAWNER);
final ItemMeta meta = item.getItemMeta();
if (meta != null){
- meta.setDisplayName(info.customName == null ? "LM spawner" : info.customName);
- List lore = new LinkedList<>();
-
- try {
- int itemsCount = 0;
- final StringBuilder loreLine = new StringBuilder();
- for (final Field f : info.getClass().getDeclaredFields()) {
- if (!Modifier.isPublic(f.getModifiers())) continue;
- if (f.get(info) == null) continue;
- final String name = f.getName();
- if (f.isAnnotationPresent(DoNotMerge.class)) continue;
-
- if ("-1".equals(f.get(info).toString()) && (name.equals("minLevel") || name.equals("maxLevel")))
- continue;
-
- if (itemsCount > 2){
- lore.add(loreLine.toString());
- loreLine.setLength(0);
- itemsCount = 0;
- }
-
- if (loreLine.length() > 0) loreLine.append(", ");
- loreLine.append(String.format("&7%s: &b%s&7", name, f.get(info)));
- itemsCount++;
- }
- if (itemsCount > 0)
- lore.add(loreLine.toString());
- }
- catch (Exception e){
- e.printStackTrace();
- }
-
- if (!info.noLore && info.lore == null && info.customLore == null) {
- lore = Utils.colorizeAllInList(lore);
- meta.setLore(lore);
-
- final StringBuilder sbLore = new StringBuilder();
- for (final String loreLine : lore) {
- if (sbLore.length() > 0) sbLore.append("\n");
- sbLore.append(loreLine);
- }
- meta.getPersistentDataContainer().set(info.main.namespaced_keys.keySpawner_Lore, PersistentDataType.STRING, sbLore.toString());
- }
- else if (!info.noLore || info.customLore != null){
- final String useLore = info.customLore == null ?
- info.lore : MessageUtils.colorizeAll(info.customLore).replace("\\n", "\n");
-
- lore.clear();
- lore.addAll(List.of(useLore.split("\n")));
- meta.setLore(lore);
- meta.getPersistentDataContainer().set(info.main.namespaced_keys.keySpawner_Lore, PersistentDataType.STRING, useLore);
- }
+ setMetaItems(meta, info);
meta.getPersistentDataContainer().set(info.main.namespaced_keys.keySpawner, PersistentDataType.INTEGER, 1);
meta.getPersistentDataContainer().set(info.main.namespaced_keys.keySpawner_MinLevel, PersistentDataType.INTEGER, info.minLevel);
meta.getPersistentDataContainer().set(info.main.namespaced_keys.keySpawner_MaxLevel, PersistentDataType.INTEGER, info.maxLevel);
if (!Utils.isNullOrEmpty(info.customDropId))
meta.getPersistentDataContainer().set(info.main.namespaced_keys.keySpawner_CustomDropId, PersistentDataType.STRING, info.customDropId);
- if (!info.spawnType.equals(EntityType.UNKNOWN))
+ if (info.spawnType != EntityType.UNKNOWN)
meta.getPersistentDataContainer().set(info.main.namespaced_keys.keySpawner_SpawnType, PersistentDataType.STRING, info.spawnType.toString());
if (info.spawnRange != null)
meta.getPersistentDataContainer().set(info.main.namespaced_keys.keySpawner_SpawnRange, PersistentDataType.INTEGER, info.spawnRange);
@@ -460,30 +281,22 @@ else if (!info.noLore || info.customLore != null){
}
if (useInvSlotNum == -1){
- List message = info.main.messagesCfg.getStringList("command.levelledmobs.spawner.inventory-full");
- message = Utils.replaceAllInList(message, "%prefix%", info.main.configUtils.getPrefix());
- message = Utils.replaceAllInList(message, "%label%", info.label);
- message = Utils.colorizeAllInList(message);
- message.forEach(info.player::sendMessage);
+ showMessage("command.levelledmobs.spawner.inventory-full", info.player);
return;
}
info.player.getInventory().setItem(useInvSlotNum, item);
+ final String playerName = VersionUtils.isRunningPaper() ?
+ PaperUtils.getPlayerDisplayName(info.player) : SpigotUtils.getPlayerDisplayName(info.player);
+
+ final List message = getMessage("command.levelledmobs.spawner.spawner-give-message-console",
+ new String[]{ "%minlevel%", "%maxlevel%", "%playername%" },
+ new String[]{String.valueOf(info.minLevel), String.valueOf(info.maxLevel), playerName }
+ );
+
+ if (!message.isEmpty()) Utils.logger.info(message.get(0).replace(main.configUtils.getPrefix() + " ", ""));
- List message = info.main.messagesCfg.getStringList("command.levelledmobs.spawner.spawner-give-message");
- message = Utils.replaceAllInList(message, "%prefix%", info.main.configUtils.getPrefix());
- message = Utils.replaceAllInList(message, "%label%", info.label);
- message = Utils.colorizeAllInList(message);
- message.forEach(info.player::sendMessage);
-
- message = info.main.messagesCfg.getStringList("command.levelledmobs.spawner.spawner-give-message-console");
- message = Utils.replaceAllInList(message, "%prefix%", info.main.configUtils.getPrefix());
- message = Utils.replaceAllInList(message, "%label%", info.label);
- message = Utils.replaceAllInList(message, "%minlevel%", String.valueOf(info.minLevel));
- message = Utils.replaceAllInList(message, "%maxlevel%", String.valueOf(info.maxLevel));
- message = Utils.replaceAllInList(message, "%playername%", info.player.getDisplayName());
- message = Utils.colorizeAllInList(message);
- if (!message.isEmpty()) Utils.logger.info(message.get(0));
+ showMessage("command.levelledmobs.spawner.spawner-give-message", info.player);
}
@Override
@@ -507,7 +320,7 @@ else if (("info".equalsIgnoreCase(args[1]) || "copy".equalsIgnoreCase(args[1]))
switch (args[args.length - 2].toLowerCase()){
case "/spawntype":
final List entityNames = new LinkedList<>();
- for (EntityType entityType : EntityType.values())
+ for (final EntityType entityType : EntityType.values())
entityNames.add(entityType.toString().toLowerCase());
return entityNames;
@@ -532,65 +345,7 @@ else if (("info".equalsIgnoreCase(args[1]) || "copy".equalsIgnoreCase(args[1]))
}
}
- final Set commandsList = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
- commandsList.addAll(allSpawnerOptions);
-
- boolean inQuotes = false;
-
- for (int i = 1; i < args.length; i++) {
- final String arg = args[i];
-
- if (arg.startsWith("\"") && !arg.endsWith("\""))
- inQuotes = true;
- else if (inQuotes && arg.endsWith("\""))
- inQuotes = false;
-
- commandsList.remove(arg);
- }
-
- final String lastArg = args[args.length - 1];
-
- if (inQuotes || lastArg.length() > 0 && lastArg.charAt(lastArg.length() - 1) == '\"')
- return Collections.emptyList();
-
- final List result = new ArrayList<>(commandsList.size());
- result.addAll(commandsList);
- return result;
- }
-
- public static class CustomSpawnerInfo{
- public CustomSpawnerInfo(final LevelledMobs main, final String label){
- this.main = main;
- this.label = label;
- this.minLevel = -1;
- this.maxLevel = -1;
- this.spawnType = EntityType.UNKNOWN;
- }
-
- @DoNotMerge
- final public LevelledMobs main;
- @DoNotMerge
- final public String label;
- @DoNotMerge
- public Player player;
- public int minLevel;
- public int maxLevel;
- @DoNotMerge
- public boolean noLore;
- public Integer delay;
- public Integer maxNearbyEntities;
- public Integer minSpawnDelay;
- public Integer maxSpawnDelay;
- public Integer requiredPlayerRange;
- public Integer spawnCount;
- public Integer spawnRange;
- public String customDropId;
- @DoNotMerge
- public String customName;
- public EntityType spawnType;
- @DoNotMerge
- public String customLore;
- public String lore;
+ return checkTabCompletion(allSpawnerOptions, args);
}
private enum OperationEnum{
diff --git a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/Subcommand.java b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/Subcommand.java
index 096f83108..4cc7eb2c6 100644
--- a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/Subcommand.java
+++ b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/Subcommand.java
@@ -15,7 +15,7 @@
* @author lokka30
* @since 2.4.0
*/
-public interface Subcommand {
+interface Subcommand {
void parseSubcommand(final LevelledMobs main, final CommandSender sender, final String label, final String[] args);
diff --git a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SummonMobOptions.java b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SummonMobOptions.java
index 20699d698..b89048b12 100644
--- a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SummonMobOptions.java
+++ b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SummonMobOptions.java
@@ -7,18 +7,18 @@
import org.jetbrains.annotations.NotNull;
public class SummonMobOptions {
- public SummonMobOptions(@NotNull final LivingEntityPlaceHolder lmPlaceHolder, final CommandSender sender){
+ SummonMobOptions(@NotNull final LivingEntityPlaceHolder lmPlaceHolder, final CommandSender sender){
this.lmPlaceHolder = lmPlaceHolder;
this.sender = sender;
}
@NotNull
- public final LivingEntityPlaceHolder lmPlaceHolder;
+ final LivingEntityPlaceHolder lmPlaceHolder;
public final CommandSender sender;
- public SummonSubcommand.SummonType summonType;
+ SummonSubcommand.SummonType summonType;
public int amount;
- public RequestedLevel requestedLevel;
+ RequestedLevel requestedLevel;
public Player player;
public boolean override;
- public String nbtData;
+ String nbtData;
}
diff --git a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SummonSubcommand.java b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SummonSubcommand.java
index af9e8bdbe..6a841a439 100644
--- a/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SummonSubcommand.java
+++ b/src/main/java/me/lokka30/levelledmobs/commands/subcommands/SummonSubcommand.java
@@ -5,7 +5,10 @@
package me.lokka30.levelledmobs.commands.subcommands;
import me.lokka30.levelledmobs.LevelledMobs;
+import me.lokka30.levelledmobs.commands.MessagesBase;
+import me.lokka30.levelledmobs.managers.LevelManager;
import me.lokka30.levelledmobs.misc.*;
+import me.lokka30.microlib.other.VersionUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
@@ -29,10 +32,21 @@
* @author stumper66
* @since v2.0.0
*/
-public class SummonSubcommand implements Subcommand {
+public class SummonSubcommand extends MessagesBase implements Subcommand {
+ public SummonSubcommand(final LevelledMobs main){
+ super(main);
+ }
@Override
- public void parseSubcommand(final LevelledMobs main, final CommandSender sender, final String label, @NotNull final String @NotNull [] args) {
+ public void parseSubcommand(final LevelledMobs main, final @NotNull CommandSender sender, final String label, @NotNull final String @NotNull [] args) {
+ commandSender = sender;
+ messageLabel = label;
+
+ if (!sender.hasPermission("levelledmobs.command.summon")) {
+ main.configUtils.sendNoPermissionMsg(sender);
+ return;
+ }
+
boolean useOverride = false;
final List useArgs = new LinkedList<>();
int startOfNbt = -1;
@@ -64,52 +78,37 @@ else if (startOfNbt >= 0 && endOfNbt == -1 && arg.endsWith("}"))
final String[] useArgs2 = new String[useArgs.size()];
useArgs.toArray(useArgs2);
- parseSubcommand2(main, sender, label, useArgs2, useOverride, nbtData);
+ parseSubcommand2(useArgs2, useOverride, nbtData);
}
- private void parseSubcommand2(final LevelledMobs main, @NotNull final CommandSender sender, final String label,
- final String[] args, final boolean override, final String nbtData) {
- if (!sender.hasPermission("levelledmobs.command.summon")) {
- main.configUtils.sendNoPermissionMsg(sender);
- return;
- }
-
+ private void parseSubcommand2(final String @NotNull [] args, final boolean override, final String nbtData) {
if (args.length < 4) {
- sendMainUsage(sender, label, main);
+ showMessage("command.levelledmobs.summon.usage");
return;
}
- int amount;
+ final int amount;
try {
amount = Integer.parseInt(args[1]);
- } catch (NumberFormatException ex) {
- List messages = main.messagesCfg.getStringList("command.levelledmobs.summon.invalid-amount");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.colorizeAllInList(messages);
- messages = Utils.replaceAllInList(messages, "%amount%", args[1]); // This is after colorize so that args[1] is not colorized.
- messages.forEach(sender::sendMessage);
+ } catch (final NumberFormatException ex) {
+ showMessage("command.levelledmobs.summon.invalid-amount", "%amount%", args[1]);
+ // messages = Utils.replaceAllInList(messages, "%amount%", args[1]); // This is after colorize so that args[1] is not colorized.
return;
}
- EntityType entityType;
+ final EntityType entityType;
try {
entityType = EntityType.valueOf(args[2].toUpperCase());
- } catch (IllegalArgumentException ex) {
- List messages = main.messagesCfg.getStringList("command.levelledmobs.summon.invalid-entity-type");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.colorizeAllInList(messages);
- messages = Utils.replaceAllInList(messages, "%entityType%", args[2]); // This is after colorize so that args[2] is not colorized.
- messages.forEach(sender::sendMessage);
+ } catch (final IllegalArgumentException ex) {
+ showMessage("command.levelledmobs.summon.invalid-entity-type", "%entityType%", args[2]);
+ // messages = Utils.replaceAllInList(messages, "%entityType%", args[2]); // This is after colorize so that args[2] is not colorized.
return;
}
final RequestedLevel requestedLevel = new RequestedLevel();
if (!requestedLevel.setLevelFromString(args[3])){
- List messages = main.messagesCfg.getStringList("command.levelledmobs.summon.invalid-level");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.colorizeAllInList(messages);
- messages = Utils.replaceAllInList(messages, "%level%", args[3]); // This is after colorize so that args[3] is not colorized.
- messages.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.summon.invalid-level", "%level%", args[3]);
+ //messages = Utils.replaceAllInList(messages, "%level%", args[3]); // This is after colorize so that args[3] is not colorized.
return;
}
@@ -125,44 +124,35 @@ private void parseSubcommand2(final LevelledMobs main, @NotNull final CommandSen
summonType = SummonType.AT_LOCATION;
break;
default:
- List messages = main.messagesCfg.getStringList("command.levelledmobs.summon.invalid-summon-type");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.colorizeAllInList(messages);
- messages = Utils.replaceAllInList(messages, "%summonType%", args[4]); // This is after colorize so args[4] is not colorized.
- messages.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.summon.invalid-level", "%summonType%", args[4]);
+ // messages = Utils.replaceAllInList(messages, "%summonType%", args[4]); // This is after colorize so args[4] is not colorized.
return;
}
}
if (summonType == SummonType.HERE) {
- if (!(sender instanceof Player) && !(sender instanceof BlockCommandSender)){
- List messages = main.messagesCfg.getStringList("command.levelledmobs.summon.invalid-summon-type-console");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
+ if (!(commandSender instanceof Player) && !(commandSender instanceof BlockCommandSender)){
+ showMessage("command.levelledmobs.summon.invalid-summon-type-console");
return;
}
if (args.length == 4 || args.length == 5) {
Player player = null;
- if (sender instanceof Player) player = (Player) sender;
+ if (commandSender instanceof Player) player = (Player) commandSender;
final Location location = (player != null) ?
- ((Player) sender).getLocation() : ((BlockCommandSender) sender).getBlock().getLocation();
+ ((Player) commandSender).getLocation() : ((BlockCommandSender) commandSender).getBlock().getLocation();
if (location.getWorld() == null) {
- List messages = main.messagesCfg.getStringList("common.player-offline");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.colorizeAllInList(messages);
- messages = Utils.replaceAllInList(messages, "%player%", (player != null) ?
- player.getDisplayName() : "(null)");
- messages.forEach(sender::sendMessage);
+ final String playerName = VersionUtils.isRunningPaper() ?
+ PaperUtils.getPlayerDisplayName(player) : SpigotUtils.getPlayerDisplayName(player);
+ showMessage("common.player-offline", "%player%", playerName);
return;
}
final LivingEntityPlaceHolder lmPlaceHolder = LivingEntityPlaceHolder.getInstance(entityType, location, main);
- final SummonMobOptions options = new SummonMobOptions(lmPlaceHolder, sender);
+ final SummonMobOptions options = new SummonMobOptions(lmPlaceHolder, commandSender);
options.amount = amount;
options.requestedLevel = requestedLevel;
options.summonType = summonType;
@@ -172,13 +162,9 @@ private void parseSubcommand2(final LevelledMobs main, @NotNull final CommandSen
summonMobs(options);
lmPlaceHolder.free();
- } else {
- List messages = main.messagesCfg.getStringList("command.levelledmobs.summon.here.usage");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
}
+ else
+ showMessage("command.levelledmobs.summon.here.usage");
} else if (summonType == SummonType.AT_PLAYER) {
if (args.length == 6) {
@@ -189,9 +175,9 @@ private void parseSubcommand2(final LevelledMobs main, @NotNull final CommandSen
final Player target = Bukkit.getPlayer(args[5]);
if (target == null) {
offline = true;
- } else if (sender instanceof Player) {
+ } else if (commandSender instanceof Player) {
// Vanished player compatibility.
- final Player player = (Player) sender;
+ final Player player = (Player) commandSender;
if (!player.canSee(target) && !player.isOp()) {
offline = true;
}
@@ -200,16 +186,13 @@ private void parseSubcommand2(final LevelledMobs main, @NotNull final CommandSen
}
if (offline || world == null) {
- List messages = main.messagesCfg.getStringList("common.player-offline");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.colorizeAllInList(messages);
- messages = Utils.replaceAllInList(messages, "%player%", args[5]); // This is after colorize so that args[5] is not colorized.
- messages.forEach(sender::sendMessage);
+ showMessage("common.player-offline", "%player%", args[5]);
+ // messages = Utils.replaceAllInList(messages, "%player%", args[5]); // This is after colorize so that args[5] is not colorized.
return;
}
final LivingEntityPlaceHolder lmPlaceHolder = LivingEntityPlaceHolder.getInstance(entityType, location, main);
- final SummonMobOptions options = new SummonMobOptions(lmPlaceHolder, sender);
+ final SummonMobOptions options = new SummonMobOptions(lmPlaceHolder, commandSender);
options.amount = amount;
options.requestedLevel = requestedLevel;
options.summonType = summonType;
@@ -219,54 +202,39 @@ private void parseSubcommand2(final LevelledMobs main, @NotNull final CommandSen
summonMobs(options);
lmPlaceHolder.free();
- } else {
- List messages = main.messagesCfg.getStringList("command.levelledmobs.summon.atPlayer.usage");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
- }
+ } else
+ showMessage("command.levelledmobs.summon.atPlayer.usage");
} else { // At Location
if (args.length == 8 || args.length == 9) {
final String worldName;
if (args.length == 8) {
- if (sender instanceof Player)
- worldName = ((Player) sender).getWorld().getName();
- else if (sender instanceof BlockCommandSender)
- worldName = ((BlockCommandSender) sender).getBlock().getWorld().getName();
+ if (commandSender instanceof Player)
+ worldName = ((Player) commandSender).getWorld().getName();
+ else if (commandSender instanceof BlockCommandSender)
+ worldName = ((BlockCommandSender) commandSender).getBlock().getWorld().getName();
else {
- List messages = main.messagesCfg.getStringList("command.levelledmobs.summon.atLocation.usage-console");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.summon.atLocation.usage-console");
return;
}
} else { //args.length==9
final World world = Bukkit.getWorld(args[8]);
if (world == null) {
- List messages = main.messagesCfg.getStringList("command.levelledmobs.summon.atLocation.invalid-world");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.colorizeAllInList(messages);
- messages = Utils.replaceAllInList(messages, "%world%", args[8]); //This is after colorize so that args[8] is not colorized.
- messages.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.summon.atLocation.usage-console", "%world%", args[8]);
+ // messages = Utils.replaceAllInList(messages, "%world%", args[8]); //This is after colorize so that args[8] is not colorized.
return;
} else
worldName = world.getName();
}
- Location location = getRelativeLocation(sender, args[5], args[6], args[7], worldName);
+ final Location location = getRelativeLocation(commandSender, args[5], args[6], args[7], worldName);
- if (location == null || location.getWorld() == null) {
- List messages = main.messagesCfg.getStringList("command.levelledmobs.summon.atLocation.invalid-location");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
- } else {
- LivingEntityPlaceHolder lmPlaceHolder = LivingEntityPlaceHolder.getInstance(entityType, location, main);
- final SummonMobOptions options = new SummonMobOptions(lmPlaceHolder, sender);
+ if (location == null || location.getWorld() == null)
+ showMessage("command.levelledmobs.summon.atLocation.invalid-location");
+ else {
+ final LivingEntityPlaceHolder lmPlaceHolder = LivingEntityPlaceHolder.getInstance(entityType, location, main);
+ final SummonMobOptions options = new SummonMobOptions(lmPlaceHolder, commandSender);
options.amount = amount;
options.requestedLevel = requestedLevel;
options.summonType = summonType;
@@ -275,13 +243,8 @@ else if (sender instanceof BlockCommandSender)
summonMobs(options);
lmPlaceHolder.free();
}
- } else {
- List messages = main.messagesCfg.getStringList("command.levelledmobs.summon.atLocation.usage");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
- }
+ } else
+ showMessage("command.levelledmobs.summon.atLocation.usage");
}
}
@@ -303,8 +266,8 @@ public List parseTabCompletions(final LevelledMobs main, final @NotNull
//
if (args.length == 3) {
- List entityNames = new LinkedList<>();
- for (EntityType entityType : EntityType.values()) {
+ final List entityNames = new LinkedList<>();
+ for (final EntityType entityType : EntityType.values()) {
entityNames.add(entityType.toString().toLowerCase());
}
return entityNames;
@@ -337,10 +300,10 @@ public List parseTabCompletions(final LevelledMobs main, final @NotNull
switch (args[4].toLowerCase()) {
case "atplayer":
if (args.length == 6) {
- List suggestions = new LinkedList<>();
- for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
+ final List suggestions = new LinkedList<>();
+ for (final Player onlinePlayer : Bukkit.getOnlinePlayers()) {
if (sender instanceof Player) {
- Player player = (Player) sender;
+ final Player player = (Player) sender;
if (player.canSee(onlinePlayer) || player.isOp()) {
suggestions.add(onlinePlayer.getName());
}
@@ -361,7 +324,7 @@ public List parseTabCompletions(final LevelledMobs main, final @NotNull
if (args.length < 9) { // args 6, 7 and 8 = x, y and z
return Collections.singletonList("~");
} else if (args.length == 9) {
- List worlds = new LinkedList<>();
+ final List worlds = new LinkedList<>();
Bukkit.getWorlds().forEach(world -> worlds.add(world.getName()));
return worlds;
} else if (args.length == 10){
@@ -391,15 +354,6 @@ enum SummonType {
AT_LOCATION
}
- private void sendMainUsage(@NotNull final CommandSender sender, final String label, @NotNull final LevelledMobs main) {
-
- List messages = main.messagesCfg.getStringList("command.levelledmobs.summon.usage");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", label);
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(sender::sendMessage);
- }
-
private void summonMobs(@NotNull final SummonMobOptions options) {
final CommandSender sender = options.sender;
@@ -438,7 +392,7 @@ private void summonMobs(@NotNull final SummonMobOptions options) {
List messages = main.messagesCfg.getStringList("command.levelledmobs.summon.amount-limited.max");
messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%maxAmount%", maxAmount + "");
+ messages = Utils.replaceAllInList(messages, "%maxAmount%", String.valueOf(maxAmount));
messages = Utils.colorizeAllInList(messages);
messages.forEach(sender::sendMessage);
}
@@ -452,7 +406,7 @@ private void summonMobs(@NotNull final SummonMobOptions options) {
List messages = main.messagesCfg.getStringList("command.levelledmobs.summon.level-limited.min");
messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%minLevel%", minLevel + "");
+ messages = Utils.replaceAllInList(messages, "%minLevel%", String.valueOf(minLevel));
messages = Utils.colorizeAllInList(messages);
messages.forEach(sender::sendMessage);
}
@@ -462,7 +416,7 @@ private void summonMobs(@NotNull final SummonMobOptions options) {
List messages = main.messagesCfg.getStringList("command.levelledmobs.summon.level-limited.max");
messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%maxLevel%", maxLevel + "");
+ messages = Utils.replaceAllInList(messages, "%maxLevel%", String.valueOf(maxLevel));
messages = Utils.colorizeAllInList(messages);
messages.forEach(sender::sendMessage);
}
@@ -474,7 +428,6 @@ private void summonMobs(@NotNull final SummonMobOptions options) {
final int distFromPlayer = main.settingsCfg.getInt("summon-command-spawn-distance-from-player", 5);
if (distFromPlayer > 0 && target != null) {
int useDistFromPlayer = distFromPlayer;
- final double direction = target.getEyeLocation().getYaw();
final Location origLocation = location;
// try up to 50 times to find a open spot to spawn the mob. Keep getting closer to the player if needed
for (int i = 0; i < 50; i++) {
@@ -487,27 +440,27 @@ private void summonMobs(@NotNull final SummonMobOptions options) {
break; // found an open spot
}
} else if (target == null && sender instanceof BlockCommandSender) {
- BlockCommandSender bcs = (BlockCommandSender) sender;
// increase the y by one so they don't spawn inside the command block
location = new Location(location.getWorld(), location.getBlockX(), location.getBlockY() + 1, location.getBlockZ());
}
}
- main.levelManager.summonedEntityType = options.lmPlaceHolder.getEntityType();
- main.levelManager.summonedLocation = location;
-
for (int i = 0; i < options.amount; i++) {
assert location.getWorld() != null;
- final Entity entity = location.getWorld().spawnEntity(location, options.lmPlaceHolder.getEntityType());
-
final int useLevel = options.requestedLevel.hasLevelRange ?
- ThreadLocalRandom.current().nextInt(options.requestedLevel.levelRangeMin, options.requestedLevel.levelRangeMax + 1) :
+ ThreadLocalRandom.current().nextInt(options.requestedLevel.levelRangeMin, options.requestedLevel.levelRangeMax + 1) :
options.requestedLevel.level;
+ final Entity entity = location.getWorld().spawnEntity(location, options.lmPlaceHolder.getEntityType());
+
if (entity instanceof LivingEntity) {
final LivingEntityWrapper lmEntity = LivingEntityWrapper.getInstance((LivingEntity) entity, main);
- lmEntity.nbtData = options.nbtData;
+ synchronized (LevelManager.summonedOrSpawnEggs_Lock){
+ main.levelManager.summonedOrSpawnEggs.put(lmEntity.getLivingEntity(), null);
+ }
+ if (!Utils.isNullOrEmpty(options.nbtData))
+ lmEntity.nbtData = List.of(options.nbtData);
lmEntity.summonedSender = sender;
main.levelInterface.applyLevelToMob(lmEntity, useLevel, true, options.override, new HashSet<>(Collections.singletonList(AdditionalLevelInformation.NOT_APPLICABLE)));
synchronized (lmEntity.getLivingEntity().getPersistentDataContainer()){
@@ -517,44 +470,33 @@ private void summonMobs(@NotNull final SummonMobOptions options) {
}
}
- main.levelManager.summonedEntityType = EntityType.UNKNOWN;
- main.levelManager.summonedLocation = null;
-
switch (options.summonType) {
case HERE:
- List hereSuccessmessages = main.messagesCfg.getStringList("command.levelledmobs.summon.here.success");
- hereSuccessmessages = Utils.replaceAllInList(hereSuccessmessages, "%prefix%", main.configUtils.getPrefix());
- hereSuccessmessages = Utils.replaceAllInList(hereSuccessmessages, "%amount%", options.amount + "");
- hereSuccessmessages = Utils.replaceAllInList(hereSuccessmessages, "%level%", options.requestedLevel.toString());
- hereSuccessmessages = Utils.replaceAllInList(hereSuccessmessages, "%entity%", options.lmPlaceHolder.getTypeName());
- hereSuccessmessages = Utils.colorizeAllInList(hereSuccessmessages);
- hereSuccessmessages.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.summon.here.success",
+ new String[]{ "%amount%", "%level%", "%entity%"},
+ new String[]{String.valueOf(options.amount), options.requestedLevel.toString(), options.lmPlaceHolder.getTypeName() }
+ );
break;
case AT_LOCATION:
- List atLocationSuccessMessages = main.messagesCfg.getStringList("command.levelledmobs.summon.atLocation.success");
- atLocationSuccessMessages = Utils.replaceAllInList(atLocationSuccessMessages, "%prefix%", main.configUtils.getPrefix());
- atLocationSuccessMessages = Utils.replaceAllInList(atLocationSuccessMessages, "%amount%", options.amount + "");
- atLocationSuccessMessages = Utils.replaceAllInList(atLocationSuccessMessages, "%level%", options.requestedLevel.toString());
- atLocationSuccessMessages = Utils.replaceAllInList(atLocationSuccessMessages, "%entity%", options.lmPlaceHolder.getTypeName());
- atLocationSuccessMessages = Utils.replaceAllInList(atLocationSuccessMessages, "%x%", location.getBlockX() + "");
- atLocationSuccessMessages = Utils.replaceAllInList(atLocationSuccessMessages, "%y%", location.getBlockY() + "");
- atLocationSuccessMessages = Utils.replaceAllInList(atLocationSuccessMessages, "%z%", location.getBlockZ() + "");
- atLocationSuccessMessages = Utils.replaceAllInList(atLocationSuccessMessages, "%world%", location.getWorld() == null ? "(null)" : location.getWorld().getName());
- atLocationSuccessMessages = Utils.colorizeAllInList(atLocationSuccessMessages);
- atLocationSuccessMessages.forEach(sender::sendMessage);
+ showMessage("command.levelledmobs.summon.atLocation.success",
+ new String[]{ "%amount%", "%level%", "%entity%", "%x%", "%x%", "%x%", "%world%"},
+ new String[]{String.valueOf(options.amount), options.requestedLevel.toString(), options.lmPlaceHolder.getTypeName(),
+ String.valueOf(location.getBlockX()), String.valueOf(location.getBlockY()), String.valueOf(location.getBlockX()),
+ location.getWorld() == null ? "(null)" : location.getWorld().getName() }
+ );
+
break;
case AT_PLAYER:
- List atPlayerSuccessMessages = main.messagesCfg.getStringList("command.levelledmobs.summon.atPlayer.success");
- atPlayerSuccessMessages = Utils.replaceAllInList(atPlayerSuccessMessages, "%prefix%", main.configUtils.getPrefix());
- atPlayerSuccessMessages = Utils.replaceAllInList(atPlayerSuccessMessages, "%amount%", options.amount + "");
- atPlayerSuccessMessages = Utils.replaceAllInList(atPlayerSuccessMessages, "%level%", options.requestedLevel.toString());
- atPlayerSuccessMessages = Utils.replaceAllInList(atPlayerSuccessMessages, "%entity%", options.lmPlaceHolder.getTypeName());
- atPlayerSuccessMessages = Utils.replaceAllInList(atPlayerSuccessMessages, "%targetUsername%", target == null ? "(null)" : target.getName());
- atPlayerSuccessMessages = Utils.replaceAllInList(atPlayerSuccessMessages, "%targetDisplayname%", target == null ? "(null)" : target.getDisplayName());
- atPlayerSuccessMessages = Utils.colorizeAllInList(atPlayerSuccessMessages);
- atPlayerSuccessMessages.forEach(sender::sendMessage);
+ final String playerName = VersionUtils.isRunningPaper() ?
+ PaperUtils.getPlayerDisplayName(target) : SpigotUtils.getPlayerDisplayName(target);
+ showMessage("command.levelledmobs.summon.atPlayer.success",
+ new String[]{ "%amount%", "%level%", "%entity%", "%targetUsername%", "%targetDisplayname%"},
+ new String[]{String.valueOf(options.amount), options.requestedLevel.toString(), options.lmPlaceHolder.getTypeName(),
+ target == null ? "(null)" : target.getName(), target == null ? "(null)" : playerName }
+ );
+
break;
default:
throw new IllegalStateException("Unexpected SummonType value of " + options.summonType + "!");
@@ -610,10 +552,10 @@ private Location getRelativeLocation(final CommandSender sender, final String xS
x = ((BlockCommandSender) sender).getBlock().getX();
if (xStr.length() > 1) {
- double addition;
+ final double addition;
try {
addition = Double.parseDouble(xStr.substring(1));
- } catch (NumberFormatException ex) {
+ } catch (final NumberFormatException ex) {
return null;
}
x += addition;
@@ -628,10 +570,10 @@ private Location getRelativeLocation(final CommandSender sender, final String xS
y = ((BlockCommandSender) sender).getBlock().getY();
if (yStr.length() > 1) {
- double addition;
+ final double addition;
try {
addition = Double.parseDouble(yStr.substring(1));
- } catch (NumberFormatException ex) {
+ } catch (final NumberFormatException ex) {
return null;
}
@@ -647,10 +589,10 @@ private Location getRelativeLocation(final CommandSender sender, final String xS
z = ((BlockCommandSender) sender).getBlock().getZ();
if (zStr.length() > 1) {
- double addition;
+ final double addition;
try {
addition = Double.parseDouble(zStr.substring(1));
- } catch (NumberFormatException ex) {
+ } catch (final NumberFormatException ex) {
return null;
}
z += addition;
@@ -663,21 +605,21 @@ private Location getRelativeLocation(final CommandSender sender, final String xS
if (!xRelative) {
try {
x = Double.parseDouble(xStr);
- } catch (NumberFormatException ex) {
+ } catch (final NumberFormatException ex) {
return null;
}
}
if (!yRelative) {
try {
y = Double.parseDouble(yStr);
- } catch (NumberFormatException ex) {
+ } catch (final NumberFormatException ex) {
return null;
}
}
if (!zRelative) {
try {
z = Double.parseDouble(zStr);
- } catch (NumberFormatException ex) {
+ } catch (final NumberFormatException ex) {
return null;
}
}
diff --git a/src/main/java/me/lokka30/levelledmobs/compatibility/Compat1_16.java b/src/main/java/me/lokka30/levelledmobs/compatibility/Compat1_16.java
index b6a3269fe..c77b72566 100644
--- a/src/main/java/me/lokka30/levelledmobs/compatibility/Compat1_16.java
+++ b/src/main/java/me/lokka30/levelledmobs/compatibility/Compat1_16.java
@@ -46,7 +46,7 @@ public static HashSet getPassiveMobs() {
private static boolean shouldIncludePiglinBrutes(){
final String ver = Bukkit.getBukkitVersion();
// 1.17.1-R0.1-SNAPSHOT
- final int dash = ver.indexOf("-");
+ final int dash = ver.indexOf('-');
if (dash < 1) return false;
final String verCorrected = ver.substring(0, dash);
diff --git a/src/main/java/me/lokka30/levelledmobs/customdrops/CustomCommand.java b/src/main/java/me/lokka30/levelledmobs/customdrops/CustomCommand.java
index 6570a234f..0787bd091 100644
--- a/src/main/java/me/lokka30/levelledmobs/customdrops/CustomCommand.java
+++ b/src/main/java/me/lokka30/levelledmobs/customdrops/CustomCommand.java
@@ -19,23 +19,23 @@
*/
public class CustomCommand extends CustomDropBase {
- public CustomCommand(@NotNull final CustomDropsDefaults defaults){
+ CustomCommand(@NotNull final CustomDropsDefaults defaults){
super(defaults);
this.rangedEntries = new TreeMap<>();
this.commands = new LinkedList<>();
}
- public String commandName;
+ String commandName;
@NotNull
final public List commands;
@NotNull
- final public Map rangedEntries;
+ final Map rangedEntries;
public CustomCommand cloneItem() {
CustomCommand copy = null;
try {
copy = (CustomCommand) super.clone();
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
}
diff --git a/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropBase.java b/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropBase.java
index 69003140f..f8c3a13fe 100644
--- a/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropBase.java
+++ b/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropBase.java
@@ -4,7 +4,9 @@
package me.lokka30.levelledmobs.customdrops;
+import me.lokka30.levelledmobs.misc.CachedModalList;
import me.lokka30.levelledmobs.misc.Utils;
+import org.bukkit.event.entity.EntityDamageEvent;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedList;
@@ -20,60 +22,61 @@
*/
public class CustomDropBase implements Cloneable {
- public CustomDropBase(@NotNull final CustomDropsDefaults defaults) {
+ CustomDropBase(@NotNull final CustomDropsDefaults defaults) {
this.amount = defaults.amount;
this.permissions = new LinkedList<>();
}
- int amount;
+ private int amount;
int amountRangeMin;
- int amountRangeMax;
- boolean hasAmountRange;
+ private int amountRangeMax;
+ private boolean hasAmountRange;
public int minLevel;
public int maxLevel;
public int priority;
- public int maxDropGroup;
- public int minPlayerLevel;
- public int maxPlayerLevel;
- public double chance;
- public boolean playerCausedOnly;
- public boolean noSpawner;
- public String groupId;
- public String playerLevelVariable;
+ int maxDropGroup;
+ int minPlayerLevel;
+ int maxPlayerLevel;
+ public float chance;
+ boolean playerCausedOnly;
+ boolean noSpawner;
+ String groupId;
+ String playerLevelVariable;
final public List permissions;
- public final Set excludedMobs = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+ final Set excludedMobs = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+ CachedModalList causeOfDeathReqs;
public int getAmount(){
return this.amount;
}
- public void setAmount(int amount){
+ public void setAmount(final int amount){
this.amount = amount;
if (this.amount > 64) this.amount = 64;
if (this.amount < 1) this.amount = 1;
this.hasAmountRange = false;
}
- public int getAmountRangeMin(){
+ int getAmountRangeMin(){
return this.amountRangeMin;
}
- public int getAmountRangeMax(){
+ int getAmountRangeMax(){
return this.amountRangeMax;
}
- public boolean getHasAmountRange(){
+ boolean getHasAmountRange(){
return this.hasAmountRange;
}
- public String getAmountAsString(){
+ String getAmountAsString(){
if (this.hasAmountRange)
return String.format("%s-%s", this.amountRangeMin, this.amountRangeMax);
else
return String.valueOf(this.amount);
}
- public boolean setAmountRangeFromString(final String numberOrNumberRange){
+ boolean setAmountRangeFromString(final String numberOrNumberRange){
if (numberOrNumberRange == null || numberOrNumberRange.isEmpty()) return false;
if (!numberOrNumberRange.contains("-")){
@@ -99,7 +102,10 @@ public CustomDropBase cloneItem() {
CustomDropBase copy = null;
try {
copy = (CustomDropBase) super.clone();
- } catch (Exception e) {
+ if (this.causeOfDeathReqs != null)
+ //noinspection unchecked
+ copy.causeOfDeathReqs = (CachedModalList) this.causeOfDeathReqs.clone();
+ } catch (final Exception e) {
e.printStackTrace();
}
diff --git a/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropInstance.java b/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropInstance.java
index 8a17a9b66..912665477 100644
--- a/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropInstance.java
+++ b/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropInstance.java
@@ -19,8 +19,8 @@
* @author stumper66
* @since 2.4.0
*/
-public class CustomDropInstance {
- public CustomDropInstance(final EntityType associatedMob){
+class CustomDropInstance {
+ CustomDropInstance(final EntityType associatedMob){
this.associatedMob = associatedMob;
this.entityGroup = null;
this.customItems = new LinkedList<>();
@@ -28,7 +28,7 @@ public CustomDropInstance(final EntityType associatedMob){
this.isBabyMob = false;
}
- public CustomDropInstance(final EntityType associatedMob, final boolean isBabyMob){
+ CustomDropInstance(final EntityType associatedMob, final boolean isBabyMob){
this.associatedMob = associatedMob;
this.entityGroup = null;
this.customItems = new LinkedList<>();
@@ -36,7 +36,7 @@ public CustomDropInstance(final EntityType associatedMob, final boolean isBabyMo
this.isBabyMob = isBabyMob;
}
- public CustomDropInstance(final CustomUniversalGroups entityGroup){
+ CustomDropInstance(final CustomUniversalGroups entityGroup){
this.associatedMob = null;
this.entityGroup = entityGroup;
this.customItems = new LinkedList<>();
@@ -44,20 +44,16 @@ public CustomDropInstance(final CustomUniversalGroups entityGroup){
isBabyMob = false;
}
- final public EntityType associatedMob;
- final public CustomUniversalGroups entityGroup;
- final public List customItems;
- public Double overallChance;
- final public List overallPermissions;
- public boolean overrideStockDrops;
- public boolean utilizesGroupIds;
- final public boolean isBabyMob;
+ private final EntityType associatedMob;
+ private final CustomUniversalGroups entityGroup;
+ final List customItems;
+ Float overallChance;
+ final List overallPermissions;
+ boolean overrideStockDrops;
+ boolean utilizesGroupIds;
+ final boolean isBabyMob;
- public boolean getIsGroup() {
- return this.entityGroup != null;
- }
-
- public void combineDrop(CustomDropInstance dropInstance){
+ void combineDrop(final CustomDropInstance dropInstance){
if (dropInstance == null) throw new NullPointerException("dropInstance");
if (dropInstance.overrideStockDrops) this.overrideStockDrops = true;
@@ -66,8 +62,7 @@ public void combineDrop(CustomDropInstance dropInstance){
this.customItems.addAll(dropInstance.customItems);
}
- @NotNull
- public String getMobOrGroupName() {
+ @NotNull String getMobOrGroupName() {
if (this.associatedMob != null)
return this.associatedMob.name();
else if (this.entityGroup != null)
diff --git a/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropItem.java b/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropItem.java
index 75146842a..082c667d7 100644
--- a/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropItem.java
+++ b/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropItem.java
@@ -10,8 +10,6 @@
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
-import java.lang.reflect.Field;
-import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
@@ -23,15 +21,15 @@
* @since 2.5.0
*/
public class CustomDropItem extends CustomDropBase {
- public int customModelDataId;
- public double equippedSpawnChance;
- public boolean noMultiplier;
- public boolean onlyDropIfEquipped;
+ int customModelDataId;
+ float equippedSpawnChance;
+ boolean noMultiplier;
+ boolean onlyDropIfEquipped;
public String customName;
public String mobHeadTexture;
- public String nbtData;
+ String nbtData;
public List lore;
- public List itemFlags;
+ List itemFlags;
private boolean hasDamageRange;
private int damage;
private int damageRangeMin;
@@ -40,7 +38,7 @@ public class CustomDropItem extends CustomDropBase {
private Material material;
private ItemStack itemStack;
- public CustomDropItem(@NotNull final CustomDropsDefaults defaults) {
+ CustomDropItem(@NotNull final CustomDropsDefaults defaults) {
super(defaults);
if (!Utils.isNullOrEmpty(defaults.damage)) this.setDamageRangeFromString(defaults.damage);
this.customModelDataId = defaults.customModelData;
@@ -59,20 +57,14 @@ public CustomDropItem cloneItem() {
try {
copy = (CustomDropItem) super.clone();
copy.itemStack = this.itemStack.clone();
- } catch (Exception e) {
+ } catch (final Exception e) {
e.printStackTrace();
}
return copy;
}
- private static String getContent(@NotNull Object aClass, String name) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
- Field declaredField = aClass.getClass().getDeclaredField(name);
- declaredField.setAccessible(true);
- return (String) declaredField.get(aClass);
- }
-
- public boolean setDamageRangeFromString(final String numberOrNumberRange){
+ boolean setDamageRangeFromString(final String numberOrNumberRange){
if (numberOrNumberRange == null || numberOrNumberRange.isEmpty()) return false;
if (!numberOrNumberRange.contains("-")){
@@ -85,7 +77,7 @@ public boolean setDamageRangeFromString(final String numberOrNumberRange){
return true;
}
- String[] nums = numberOrNumberRange.split("-");
+ final String[] nums = numberOrNumberRange.split("-");
if (nums.length != 2) return false;
if (!Utils.isInteger(nums[0].trim()) || !Utils.isInteger(nums[1].trim())) return false;
@@ -98,20 +90,20 @@ public boolean setDamageRangeFromString(final String numberOrNumberRange){
public int getDamage() { return this.damage; }
- public void setDamage(int damage){
+ public void setDamage(final int damage){
this.damage = damage;
this.hasDamageRange = false;
}
- public int getDamageRangeMin(){
+ int getDamageRangeMin(){
return this.damageRangeMin;
}
- public int getDamageRangeMax(){
+ int getDamageRangeMax(){
return this.damageRangeMax;
}
- public boolean getHasDamageRange(){
+ boolean getHasDamageRange(){
return this.hasDamageRange;
}
@@ -120,7 +112,7 @@ public void setMaterial(final Material material){
this.itemStack = new ItemStack(this.material, 1);
}
- public String getDamageAsString(){
+ String getDamageAsString(){
if (this.hasDamageRange)
return String.format("%s-%s", this.damageRangeMin, this.damageRangeMax);
else
diff --git a/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropProcessingInfo.java b/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropProcessingInfo.java
index 3317f1e93..a795e68f5 100644
--- a/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropProcessingInfo.java
+++ b/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropProcessingInfo.java
@@ -7,8 +7,9 @@
import me.lokka30.levelledmobs.misc.LivingEntityWrapper;
import me.lokka30.levelledmobs.misc.Utils;
import me.lokka30.levelledmobs.rules.CustomDropsRuleSet;
-import me.lokka30.microlib.MessageUtils;
+import me.lokka30.microlib.messaging.MessageUtils;
import org.bukkit.entity.Player;
+import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -28,40 +29,38 @@
* @author stumper66
* @since 2.4.1
*/
-public class CustomDropProcessingInfo {
- public CustomDropProcessingInfo() {
+class CustomDropProcessingInfo {
+ CustomDropProcessingInfo() {
this.groupIDsDroppedAlready = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
this.allDropInstances = new LinkedList<>();
this.playerLevelVariableCache = new TreeMap<>();
}
public LivingEntityWrapper lmEntity;
- public int addition;
- public Player mobKiller;
+ int addition;
+ Player mobKiller;
@NotNull
- final public Map playerLevelVariableCache;
- public boolean isSpawner;
- public boolean equippedOnly;
- public boolean deathByFire;
- public boolean wasKilledByPlayer;
- public boolean doNotMultiplyDrops;
- public boolean hasOverride;
- public boolean hasCustomDropId;
- public boolean madeOverallChance;
- public boolean hasEquippedItems;
+ final Map playerLevelVariableCache;
+ boolean isSpawner;
+ boolean equippedOnly;
+ boolean deathByFire;
+ boolean wasKilledByPlayer;
+ EntityDamageEvent.DamageCause deathCause;
+ boolean doNotMultiplyDrops;
+ boolean hasOverride;
+ boolean hasCustomDropId;
+ boolean hasEquippedItems;
public String customDropId;
- public String playerLevelVariable;
- public List newDrops;
+ List newDrops;
@Nonnull
- final public Map groupIDsDroppedAlready;
- public Map> prioritizedDrops;
- @Nullable
- public CustomDropsRuleSet dropRules;
+ final Map groupIDsDroppedAlready;
+ Map> prioritizedDrops;
+ @Nullable CustomDropsRuleSet dropRules;
@NotNull
- final public List allDropInstances;
- public StringBuilder debugMessages;
+ final List allDropInstances;
+ private StringBuilder debugMessages;
- public void addDebugMessage(final String message){
+ void addDebugMessage(final String message){
if (this.debugMessages == null)
this.debugMessages = new StringBuilder();
@@ -71,7 +70,7 @@ public void addDebugMessage(final String message){
this.debugMessages.append(message);
}
- public void writeAnyDebugMessages(){
+ void writeAnyDebugMessages(){
if (this.debugMessages == null) return;
Utils.logger.info(MessageUtils.colorizeAll(this.debugMessages.toString()));
diff --git a/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropsDefaults.java b/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropsDefaults.java
index eb7cd20db..42f29b322 100644
--- a/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropsDefaults.java
+++ b/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropsDefaults.java
@@ -4,7 +4,8 @@
package me.lokka30.levelledmobs.customdrops;
-import org.bukkit.inventory.ItemFlag;
+import me.lokka30.levelledmobs.misc.CachedModalList;
+import org.bukkit.event.entity.EntityDamageEvent;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedList;
@@ -17,34 +18,33 @@
* @author stumper66
* @since 2.4.0
*/
-public class CustomDropsDefaults {
- public boolean noMultiplier;
- public boolean noSpawner;
+class CustomDropsDefaults {
+ boolean noMultiplier;
+ boolean noSpawner;
public boolean override;
- public boolean playerCausedOnly;
- public boolean onlyDropIfEquipped;
+ boolean playerCausedOnly;
+ boolean onlyDropIfEquipped;
public int amount;
public int priority;
public int minLevel;
public int maxLevel;
- public int customModelData;
- public int maxDropGroup;
- public int minPlayerLevel;
- public int maxPlayerLevel;
- public double chance;
- public double equippedSpawnChance;
- public Double overallChance;
- public String groupId;
+ int customModelData;
+ int maxDropGroup;
+ int minPlayerLevel;
+ int maxPlayerLevel;
+ public float chance;
+ float equippedSpawnChance;
+ Float overallChance;
+ String groupId;
public String damage;
- public String nbtData;
- public String playerLevelVariable;
- public List itemFlags;
- final public List permissions;
- final public List overallPermissions;
+ String playerLevelVariable;
+ public final List permissions;
+ final List overallPermissions;
+ CachedModalList causeOfDeathReqs;
- public CustomDropsDefaults() {
+ CustomDropsDefaults() {
// these are the defaults of the defaults
- this.chance = 0.2;
+ this.chance = 0.2F;
this.amount = 1;
this.minLevel = -1;
this.maxLevel = -1;
@@ -52,7 +52,7 @@ public CustomDropsDefaults() {
this.maxPlayerLevel = -1;
this.customModelData = -1;
this.priority = 0;
- this.equippedSpawnChance = 0.0;
+ this.equippedSpawnChance = 0.0F;
this.maxDropGroup = 0;
this.noMultiplier = false;
this.noSpawner = false;
@@ -62,7 +62,7 @@ public CustomDropsDefaults() {
this.overallPermissions = new LinkedList<>();
}
- public void setDefaultsFromDropItem(@NotNull final CustomDropItem drop) {
+ void setDefaultsFromDropItem(@NotNull final CustomDropItem drop) {
this.chance = drop.chance;
this.amount = drop.getAmount();
this.minLevel = drop.minLevel;
@@ -75,12 +75,11 @@ public void setDefaultsFromDropItem(@NotNull final CustomDropItem drop) {
this.noSpawner = drop.noSpawner;
this.playerCausedOnly = drop.playerCausedOnly;
this.groupId = drop.groupId;
- this.nbtData = drop.nbtData;
- this.itemFlags = drop.itemFlags;
this.minPlayerLevel = drop.minPlayerLevel;
this.maxPlayerLevel = drop.maxPlayerLevel;
this.playerLevelVariable = drop.playerLevelVariable;
this.onlyDropIfEquipped = drop.onlyDropIfEquipped;
this.permissions.addAll(drop.permissions);
+ this.causeOfDeathReqs = drop.causeOfDeathReqs;
}
}
diff --git a/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropsHandler.java b/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropsHandler.java
index 5445a74d0..88b683bc8 100644
--- a/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropsHandler.java
+++ b/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropsHandler.java
@@ -7,7 +7,8 @@
import me.lokka30.levelledmobs.LevelledMobs;
import me.lokka30.levelledmobs.misc.*;
import me.lokka30.levelledmobs.rules.LevelledMobSpawnReason;
-import me.lokka30.microlib.MessageUtils;
+import me.lokka30.microlib.messaging.MessageUtils;
+import me.lokka30.microlib.other.VersionUtils;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
@@ -36,12 +37,11 @@
public class CustomDropsHandler {
private final LevelledMobs main;
- public final TreeMap customDropsitems;
- public final TreeMap customDropsitems_Babies;
- public final TreeMap customDropsitems_groups;
- public final TreeMap customDropIDs;
- @Nullable
- public Map customItemGroups;
+ final TreeMap customDropsitems;
+ final TreeMap customDropsitems_Babies;
+ final TreeMap customDropsitems_groups;
+ final TreeMap customDropIDs;
+ @Nullable Map customItemGroups;
public final CustomDropsParser customDropsParser;
private final YmlParsingHelper ymlHelper;
@@ -79,6 +79,10 @@ public CustomDropResult getCustomItemDrops(final LivingEntityWrapper lmEntity, f
}
else
processingInfo.wasKilledByPlayer = false;
+
+ if (lmEntity.getLivingEntity().getLastDamageCause() != null)
+ processingInfo.deathCause = lmEntity.getLivingEntity().getLastDamageCause().getCause();
+
processingInfo.addition = BigDecimal.valueOf(main.mobDataManager.getAdditionsForLevel(lmEntity, Addition.CUSTOM_ITEM_DROP, 0.0))
.setScale(0, RoundingMode.HALF_DOWN).intValueExact(); // truncate double to int
@@ -93,7 +97,7 @@ public CustomDropResult getCustomItemDrops(final LivingEntityWrapper lmEntity, f
if (!equippedOnly && isCustomDropsDebuggingEnabled()) {
- String mobLevel = lmEntity.getMobLevel() > 0 ? "&r (level " + lmEntity.getMobLevel() + ")" : "";
+ final String mobLevel = lmEntity.getMobLevel() > 0 ? "&r (level " + lmEntity.getMobLevel() + ")" : "";
processingInfo.addDebugMessage("&7Custom drops for &b" + lmEntity.getNameIfBaby() + mobLevel);
processingInfo.addDebugMessage("&8- &7Groups: &b" + String.join("&7, &b", lmEntity.getApplicableGroups()) + "&7.");
}
@@ -150,7 +154,6 @@ private DropInstanceBuildResult buildDropsListFromGroupsAndEntity(final List();
info.hasOverride = false;
boolean usesGroupIds = false;
- String customDropId = null;
final boolean overrideNonDropTableDrops = info.dropRules != null && info.dropRules.override;
final String[] useIds = getDropIds(info);
@@ -172,7 +175,7 @@ private DropInstanceBuildResult buildDropsListFromGroupsAndEntity(final List customDropBases : info.prioritizedDrops.values())
+ Collections.shuffle(customDropBases);
}
if (!checkOverallPermissions(info))
@@ -233,7 +236,7 @@ private boolean checkOverallPermissions(@NotNull final CustomDropProcessingInfo
@NotNull
private String[] getDropIds(@NotNull final CustomDropProcessingInfo processingInfo){
- List dropIds = (processingInfo.dropRules != null && processingInfo.dropRules.useDropTableId != null) ?
+ final List dropIds = (processingInfo.dropRules != null && processingInfo.dropRules.useDropTableId != null) ?
Arrays.asList(processingInfo.dropRules.useDropTableId.split(",")) : new LinkedList<>();
if (processingInfo.hasCustomDropId && !dropIds.contains(processingInfo.customDropId))
@@ -252,14 +255,12 @@ private void processDropPriorities(@NotNull final CustomDropBase baseItem, @NotN
processingInfo.prioritizedDrops.put(priority, items);
}
- if (baseItem instanceof CustomDropItem && ((CustomDropItem) baseItem).equippedSpawnChance > 0.0)
+ if (baseItem instanceof CustomDropItem && ((CustomDropItem) baseItem).equippedSpawnChance > 0.0F)
processingInfo.hasEquippedItems = true;
}
private void getCustomItemsFromDropInstance(@NotNull final CustomDropProcessingInfo info){
- for (final int itemPriority : info.prioritizedDrops.keySet()) {
- final List items = info.prioritizedDrops.get(itemPriority);
-
+ for (final List items : info.prioritizedDrops.values()) {
for (final CustomDropBase drop : items)
getDropsFromCustomDropItem(info, drop);
}
@@ -277,8 +278,8 @@ private boolean checkOverallChance(@NotNull final CustomDropProcessingInfo info)
}
// we'll roll the dice to see if we get any drops at all and store it in the PDC
- final double chanceRole = ThreadLocalRandom.current().nextDouble();
- final boolean madeChance = 1.0 - chanceRole < dropInstance.overallChance;
+ final float chanceRole = (float) ThreadLocalRandom.current().nextInt(0, 100001) * 0.00001F;
+ final boolean madeChance = 1.0F - chanceRole < dropInstance.overallChance;
if (info.equippedOnly) {
synchronized (info.lmEntity.getLivingEntity().getPersistentDataContainer()) {
info.lmEntity.getPDC().set(main.namespaced_keys.overallChanceKey, PersistentDataType.INTEGER, madeChance ? 1 : 0);
@@ -293,14 +294,26 @@ private boolean checkOverallChance(@NotNull final CustomDropProcessingInfo info)
private void getDropsFromCustomDropItem(@NotNull final CustomDropProcessingInfo info, final CustomDropBase dropBase){
if (dropBase instanceof CustomCommand && info.lmEntity.getLivingEntity().hasMetadata("noCommands") ||
- info.lmEntity.deathCause.equals(EntityDamageEvent.DamageCause.VOID))
+ info.lmEntity.deathCause == EntityDamageEvent.DamageCause.VOID)
return;
if (info.equippedOnly && dropBase instanceof CustomCommand) return;
- if (info.equippedOnly && dropBase instanceof CustomDropItem && ((CustomDropItem) dropBase).equippedSpawnChance <= 0.0) return;
- if (!info.equippedOnly && dropBase.playerCausedOnly && !info.wasKilledByPlayer) return;
+ if (info.equippedOnly && dropBase instanceof CustomDropItem && ((CustomDropItem) dropBase).equippedSpawnChance <= 0.0F) return;
+ if (!info.equippedOnly && dropBase.playerCausedOnly && (dropBase.causeOfDeathReqs == null || dropBase.causeOfDeathReqs.isEmpty()) && !info.wasKilledByPlayer) return;
if (dropBase.noSpawner && info.isSpawner) return;
+ if (dropBase.causeOfDeathReqs != null && (info.deathCause == null || !Utils.isDamageCauseInModalList(dropBase.causeOfDeathReqs, info.deathCause))){
+ if (isCustomDropsDebuggingEnabled()) {
+ final String itemName = dropBase instanceof CustomDropItem ?
+ ((CustomDropItem) dropBase).getMaterial().name() : "(command)";
+ info.addDebugMessage(String.format(
+ "&8 - &7item: &b%s&7, death-cause: &b%s&7, death-cause-req: &b%s&7, dropped: &bfalse&7.",
+ itemName, info.deathCause, dropBase.causeOfDeathReqs)
+ );
+ }
+ return;
+ }
+
if (!madePlayerLevelRequirement(info, dropBase)) return;
if (dropBase.excludedMobs.contains(info.lmEntity.getTypeName())){
@@ -318,8 +331,9 @@ private void getDropsFromCustomDropItem(@NotNull final CustomDropProcessingInfo
if (!doDrop){
if (dropBase instanceof CustomDropItem) {
final CustomDropItem dropItem = (CustomDropItem) dropBase;
- if (!info.equippedOnly && ymlHelper.getStringSet(main.settingsCfg, "debug-misc").contains("CUSTOM_DROPS")) {
+ if (!info.equippedOnly && isCustomDropsDebuggingEnabled()) {
final ItemStack itemStack = info.deathByFire ? getCookedVariantOfMeat(dropItem.getItemStack()) : dropItem.getItemStack();
+
info.addDebugMessage(String.format("&8- &7level: &b%s&7, fromSpawner: &b%s&7, item: &b%s&7, minL: &b%s&7, maxL: &b%s&7, nospawner: &b%s&7, dropped: &bfalse",
info.lmEntity.getMobLevel(), info.isSpawner, itemStack.getType().name(), dropBase.minLevel, dropBase.maxLevel, dropBase.noSpawner));
}
@@ -350,16 +364,16 @@ else if (dropBase instanceof CustomCommand) {
if (!checkDropPermissions(info, dropBase)) return;
boolean didNotMakeChance = false;
- double chanceRole = 0.0;
+ float chanceRole = 0.0F;
if (!info.equippedOnly && dropBase.chance < 1.0){
- chanceRole = ThreadLocalRandom.current().nextDouble();
- if (1.0 - chanceRole >= dropBase.chance) didNotMakeChance = true;
+ chanceRole = (float) ThreadLocalRandom.current().nextInt(0, 100001) * 0.00001F;
+ if (1.0F - chanceRole >= dropBase.chance) didNotMakeChance = true;
}
- if (didNotMakeChance && !info.equippedOnly && ymlHelper.getStringSet(main.settingsCfg, "debug-misc").contains("CUSTOM_DROPS")) {
+ if (didNotMakeChance && !info.equippedOnly && isCustomDropsDebuggingEnabled()) {
if (dropBase instanceof CustomDropItem) {
- CustomDropItem dropItem = (CustomDropItem) dropBase;
+ final CustomDropItem dropItem = (CustomDropItem) dropBase;
final ItemStack itemStack = info.deathByFire ? getCookedVariantOfMeat(dropItem.getItemStack()) : dropItem.getItemStack();
if (isCustomDropsDebuggingEnabled()) {
@@ -379,7 +393,7 @@ else if (dropBase instanceof CustomCommand) {
count = info.groupIDsDroppedAlready.get(dropBase.groupId);
if (dropBase.maxDropGroup > 0 && count >= dropBase.maxDropGroup || dropBase.maxDropGroup == 0 && count > 0){
- if (ymlHelper.getStringSet(main.settingsCfg, "debug-misc").contains("CUSTOM_DROPS")) {
+ if (isCustomDropsDebuggingEnabled()) {
if (dropBase instanceof CustomDropItem) {
info.addDebugMessage(String.format("&8- &7level: &b%s&7, item: &b%s&7, gId: &b%s&7, maxDropGroup: &b%s&7, groupDropCount: &b%s&7, dropped: &bfalse",
info.lmEntity.getMobLevel(), ((CustomDropItem) dropBase).getMaterial().name(), dropBase.groupId, dropBase.maxDropGroup, count));
@@ -403,11 +417,11 @@ else if (dropBase instanceof CustomCommand) {
info.groupIDsDroppedAlready.put(dropBase.groupId, count);
- if (main.settingsCfg.getStringList("debug-misc").contains("CUSTOM_DROPS")) {
+ if (isCustomDropsDebuggingEnabled()) {
info.addDebugMessage(String.format("&8- &7level: &b%s&7, item: custom command, gId: &b%s&7, maxDropGroup: &b%s&7, groupDropCount: &b%s&7, executed: &btrue",
info.lmEntity.getMobLevel(), dropBase.groupId, dropBase.maxDropGroup, count));
}
- } else if (main.settingsCfg.getStringList("debug-misc").contains("CUSTOM_DROPS")) {
+ } else if (isCustomDropsDebuggingEnabled()) {
info.addDebugMessage(String.format("&8- &7level: &b%s&7, item: custom command, gId: &b%s&7, maxDropGroup: &b%s&7, executed: &btrue",
info.lmEntity.getMobLevel(), dropBase.groupId, dropBase.maxDropGroup));
}
@@ -421,10 +435,10 @@ else if (dropBase instanceof CustomCommand) {
}
final CustomDropItem dropItem = (CustomDropItem) dropBase;
- if (info.equippedOnly && dropItem.equippedSpawnChance < 1.0) {
- chanceRole = ThreadLocalRandom.current().nextDouble();
- if (1.0 - chanceRole >= dropItem.equippedSpawnChance){
- if (ymlHelper.getStringSet(main.settingsCfg, "debug-misc").contains("CUSTOM_DROPS")) {
+ if (info.equippedOnly && dropItem.equippedSpawnChance < 1.0F) {
+ chanceRole = (float) ThreadLocalRandom.current().nextInt(0, 100001) * 0.00001F;
+ if (1.0F - chanceRole >= dropItem.equippedSpawnChance){
+ if (isCustomDropsDebuggingEnabled()) {
info.addDebugMessage(String.format("&8- Mob: &b%s&7, &7level: &b%s&7, item: &b%s&7, spawnchance: &b%s&7, chancerole: &b%s&7, did not make spawn chance",
info.lmEntity.getTypeName(), info.lmEntity.getMobLevel(), dropItem.getMaterial().name(), dropItem.equippedSpawnChance, Utils.round(chanceRole, 4)));
}
@@ -453,7 +467,7 @@ else if (dropBase instanceof CustomCommand) {
if (newItem.getAmount() != newDropAmount) newItem.setAmount(newDropAmount);
- if (ymlHelper.getStringSet(main.settingsCfg, "debug-misc").contains("CUSTOM_DROPS")){
+ if (isCustomDropsDebuggingEnabled()){
if (info.equippedOnly) {
info.addDebugMessage(String.format(
"&8 - &7item: &b%s&7, equipChance: &b%s&7, chanceRole: &b%s&7, equipped: &btrue&7.",
@@ -471,24 +485,30 @@ else if (dropBase instanceof CustomCommand) {
damage = ThreadLocalRandom.current().nextInt(dropItem.getDamageRangeMin(), dropItem.getDamageRangeMax() + 1);
if (damage > 0 || dropItem.lore != null || dropItem.customName != null){
- ItemMeta meta = newItem.getItemMeta();
+ final ItemMeta meta = newItem.getItemMeta();
if (damage > 0 && meta instanceof Damageable)
((Damageable) meta).setDamage(damage);
if (meta != null && dropItem.lore != null && !dropItem.lore.isEmpty()){
final List newLore = new ArrayList<>(dropItem.lore.size());
- final String mobLvl = info.lmEntity.isLevelled() ?
- info.lmEntity.getMobLevel() + "" : "0";
for (final String lore : dropItem.lore){
newLore.add(main.levelManager.updateNametag(info.lmEntity, lore, false));
- meta.setLore(newLore);
+ if (VersionUtils.isRunningPaper())
+ PaperUtils.updateItemMetaLore(meta, newLore);
+ else
+ SpigotUtils.updateItemMetaLore(meta, newLore);
}
}
- if (meta != null && dropItem.customName != null && !"".equals(dropItem.customName))
- meta.setDisplayName(MessageUtils.colorizeAll(main.levelManager.updateNametag(info.lmEntity, dropItem.customName, false)));
+ if (meta != null && dropItem.customName != null && !dropItem.customName.isEmpty()) {
+ final String displayName = MessageUtils.colorizeAll(main.levelManager.updateNametag(info.lmEntity, dropItem.customName, false));
+ if (VersionUtils.isRunningPaper())
+ PaperUtils.updateItemDisplayName(meta, displayName);
+ else
+ SpigotUtils.updateItemDisplayName(meta, displayName);
+ }
newItem.setItemMeta(meta);
}
@@ -501,13 +521,13 @@ else if (dropBase instanceof CustomCommand) {
info.groupIDsDroppedAlready.put(dropItem.groupId, count);
}
- if (newItem.getType().equals(Material.PLAYER_HEAD))
+ if (newItem.getType() == Material.PLAYER_HEAD)
newItem = main.mobHeadManager.getMobHeadFromPlayerHead(newItem, info.lmEntity, dropItem);
info.newDrops.add(newItem);
}
- private boolean checkDropPermissions(final CustomDropProcessingInfo info, final @NotNull CustomDropBase dropBase){
+ private boolean checkDropPermissions(final @NotNull CustomDropProcessingInfo info, final @NotNull CustomDropBase dropBase){
if (info.equippedOnly || dropBase.permissions.isEmpty()) return true;
if (info.mobKiller == null){
@@ -544,8 +564,8 @@ private boolean checkDropPermissions(final CustomDropProcessingInfo info, final
}
private boolean checkIfMadeEquippedDropChance(final CustomDropProcessingInfo info, final @NotNull CustomDropItem item){
- if (item.equippedSpawnChance >= 1.0 || !item.onlyDropIfEquipped) return true;
- if (item.equippedSpawnChance <= 0.0) return false;
+ if (item.equippedSpawnChance >= 1.0F || !item.onlyDropIfEquipped) return true;
+ if (item.equippedSpawnChance <= 0.0F) return false;
return isMobWearingItem(item.getItemStack(), info.lmEntity.getLivingEntity());
}
@@ -589,18 +609,19 @@ private boolean madePlayerLevelRequirement(final @NotNull CustomDropProcessingIn
// check if the variable result has been cached already and use it if so
final String variableToUse = Utils.isNullOrEmpty(dropBase.playerLevelVariable) ?
"%level%" : dropBase.playerLevelVariable;
- final int mobLevel = info.lmEntity.getMobLevel();
- int levelToUse;
+ final int levelToUse;
if (info.playerLevelVariableCache.containsKey(variableToUse))
levelToUse = info.playerLevelVariableCache.get(variableToUse);
else {
- levelToUse = main.levelManager.getPlayerLevelSourceNumber(info.mobKiller, variableToUse);
+ //levelToUse = main.levelManager.getPlayerLevelSourceNumber(info.mobKiller, variableToUse);
+ final PlayerLevelSourceResult result = main.levelManager.getPlayerLevelSourceNumber(info.mobKiller, variableToUse);
+ levelToUse = result.isNumericResult ? result.numericResult : 1;
info.playerLevelVariableCache.put(variableToUse, levelToUse);
}
if (dropBase.minPlayerLevel > -1 && levelToUse < dropBase.minPlayerLevel ||
dropBase.maxPlayerLevel > -1 && levelToUse > dropBase.maxPlayerLevel){
- if (ymlHelper.getStringSet(main.settingsCfg, "debug-misc").contains("CUSTOM_DROPS")){
+ if (isCustomDropsDebuggingEnabled()){
if (dropBase instanceof CustomDropItem) {
info.addDebugMessage(String.format(
"&8 - &7Mob: &b%s&7, item: %s, lvl-src: %s, minlvl: %s, maxlvl: %s player level criteria not met",
@@ -620,9 +641,7 @@ private boolean madePlayerLevelRequirement(final @NotNull CustomDropProcessingIn
}
private void executeCommand(@NotNull final CustomCommand customCommand, @NotNull final CustomDropProcessingInfo info){
- int commandCount = 0;
for (String command : customCommand.commands){
- commandCount++;
final String playerName = info.wasKilledByPlayer ?
Objects.requireNonNull(info.lmEntity.getLivingEntity().getKiller()).getName() :
@@ -655,8 +674,9 @@ private void executeCommand(@NotNull final CustomCommand customCommand, @NotNull
private String processRangedCommand(@NotNull String command, final @NotNull CustomCommand cc){
if (cc.rangedEntries.isEmpty()) return command;
- for (final String rangedKey : cc.rangedEntries.keySet()) {
- final String rangedValue = cc.rangedEntries.get(rangedKey);
+ for (final Map.Entry rangeds : cc.rangedEntries.entrySet()) {
+ final String rangedKey = rangeds.getKey();
+ final String rangedValue = rangeds.getValue();
if (!rangedValue.contains("-")) {
command = command.replace("%" + rangedKey + "%", rangedValue);
continue;
@@ -671,7 +691,7 @@ private String processRangedCommand(@NotNull String command, final @NotNull Cust
if (max < min) min = max;
final int rangedNum = main.random.nextInt(max - min + 1) + min;
- command = command.replace("%" + rangedKey + "%", rangedNum + "");
+ command = command.replace("%" + rangedKey + "%", String.valueOf(rangedNum));
}
return command;
@@ -697,6 +717,6 @@ private ItemStack getCookedVariantOfMeat(@NotNull final ItemStack itemStack){
}
private boolean isCustomDropsDebuggingEnabled() {
- return ymlHelper.getStringSet(main.settingsCfg, "debug-misc").contains("CUSTOM_DROPS");
+ return main.companion.debugsEnabled.contains(DebugType.CUSTOM_DROPS);
}
}
diff --git a/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropsParser.java b/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropsParser.java
index eb076604e..e17ad5d3c 100644
--- a/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropsParser.java
+++ b/src/main/java/me/lokka30/levelledmobs/customdrops/CustomDropsParser.java
@@ -7,12 +7,9 @@
import me.lokka30.levelledmobs.LevelledMobs;
import me.lokka30.levelledmobs.managers.ExternalCompatibilityManager;
import me.lokka30.levelledmobs.managers.NBTManager;
-import me.lokka30.levelledmobs.misc.CustomUniversalGroups;
-import me.lokka30.levelledmobs.misc.NBTApplyResult;
-import me.lokka30.levelledmobs.misc.Utils;
-import me.lokka30.levelledmobs.misc.YmlParsingHelper;
+import me.lokka30.levelledmobs.misc.*;
import me.lokka30.levelledmobs.rules.RuleInfo;
-import me.lokka30.microlib.MessageUtils;
+import me.lokka30.microlib.other.VersionUtils;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection;
@@ -21,6 +18,7 @@
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType;
+import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.ItemMeta;
@@ -36,9 +34,10 @@
* @author stumper66
* @since 3.0.0
*/
+@SuppressWarnings("unchecked")
public class CustomDropsParser {
- public CustomDropsParser(final LevelledMobs main, final CustomDropsHandler handler){
+ CustomDropsParser(final LevelledMobs main, final CustomDropsHandler handler){
this.main = main;
this.defaults = new CustomDropsDefaults();
this.handler = handler;
@@ -46,8 +45,8 @@ public CustomDropsParser(final LevelledMobs main, final CustomDropsHandler handl
}
private final LevelledMobs main;
- public final YmlParsingHelper ymlHelper;
- public final CustomDropsDefaults defaults;
+ final YmlParsingHelper ymlHelper;
+ private final CustomDropsDefaults defaults;
private final CustomDropsHandler handler;
private boolean hasMentionedNBTAPI_Missing;
public boolean dropsUtilizeNBTAPI;
@@ -79,9 +78,9 @@ private void processDefaults(final ConfigurationSection cs){
}
// configure bogus items so we can utilize the existing attribute parse logic
- CustomDropItem drop = new CustomDropItem(this.defaults);
+ final CustomDropItem drop = new CustomDropItem(this.defaults);
drop.setMaterial(Material.AIR);
- CustomDropInstance dropInstance = new CustomDropInstance(EntityType.AREA_EFFECT_CLOUD);
+ final CustomDropInstance dropInstance = new CustomDropInstance(EntityType.AREA_EFFECT_CLOUD);
dropInstance.customItems.add(drop);
// this sets the drop and dropinstance defaults
@@ -98,7 +97,6 @@ private void parseCustomDrops(final ConfigurationSection config){
if (config == null) return;
handler.customItemGroups = new TreeMap<>();
- final String configKey = ymlHelper.getKeyNameFromConfig(config, "defaults");
processDefaults(objectToConfigurationSection2(config, "defaults"));
final String dropTableKey = ymlHelper.getKeyNameFromConfig(config, "drop-table");
@@ -107,9 +105,10 @@ private void parseCustomDrops(final ConfigurationSection config){
if (ms != null) {
final Map itemGroups = ms.getValues(true);
- for (final String itemGroupName : itemGroups.keySet()) {
+ for (final Map.Entry itemGroup : itemGroups.entrySet()) {
+ final String itemGroupName = itemGroup.getKey();
final CustomDropInstance dropInstance = new CustomDropInstance(EntityType.AREA_EFFECT_CLOUD); // entity type doesn't matter
- parseCustomDrops2((List>) itemGroups.get(itemGroupName), dropInstance);
+ parseCustomDrops2((List>) itemGroup.getValue(), dropInstance);
if (!dropInstance.customItems.isEmpty()) {
handler.customItemGroups.put(itemGroupName, dropInstance);
handler.customDropIDs.put(itemGroupName, dropInstance);
@@ -125,18 +124,18 @@ private void parseCustomDrops(final ConfigurationSection config){
for (String mobTypeOrGroup : mobTypeOrGroups) {
mobTypeOrGroup = mobTypeOrGroup.trim();
- if ("".equals(mobTypeOrGroup)) continue;
+ if (mobTypeOrGroup.isEmpty()) continue;
if (mobTypeOrGroup.toLowerCase().startsWith("file-version")) continue;
CustomUniversalGroups universalGroup = null;
final boolean isEntityTable = (mobTypeOrGroup.equalsIgnoreCase("drop-table"));
final boolean isUniversalGroup = mobTypeOrGroup.toLowerCase().startsWith("all_");
- CustomDropInstance dropInstance;
+ final CustomDropInstance dropInstance;
if (isUniversalGroup) {
try {
universalGroup = CustomUniversalGroups.valueOf(mobTypeOrGroup.toUpperCase());
- } catch (Exception e) {
+ } catch (final Exception e) {
Utils.logger.warning("invalid universal group in customdrops.yml: " + mobTypeOrGroup);
continue;
}
@@ -153,7 +152,7 @@ private void parseCustomDrops(final ConfigurationSection config){
try {
entityType = EntityType.valueOf(mobTypeOrGroup.toUpperCase());
- } catch (Exception e) {
+ } catch (final Exception e) {
Utils.logger.warning("invalid mob type in customdrops.yml: " + mobTypeOrGroup);
continue;
}
@@ -182,7 +181,7 @@ else if (useEntityDropId == null)
Utils.logger.warning("Found a drop-table reference with no id!");
else {
final CustomDropInstance refDrop = handler.customItemGroups.get(useEntityDropId);
- for (CustomDropBase itemDrop : refDrop.customItems)
+ for (final CustomDropBase itemDrop : refDrop.customItems)
dropInstance.customItems.add(itemDrop instanceof CustomDropItem ?
((CustomDropItem) itemDrop).cloneItem() :
((CustomCommand) itemDrop).cloneItem());
@@ -211,11 +210,10 @@ else if (useEntityDropId == null)
} // next mob or group
} // next root item from file
- if (ymlHelper.getStringSet(main.settingsCfg, "debug-misc").contains("CUSTOM_DROPS")) {
+ if (main.companion.debugsEnabled.contains(DebugType.CUSTOM_DROPS)) {
int dropsCount = 0;
int commandsCount = 0;
- for (final EntityType et : handler.customDropsitems.keySet()){
- final CustomDropInstance cdi = handler.customDropsitems.get(et);
+ for (final CustomDropInstance cdi : handler.customDropsitems.values()){
for (final CustomDropBase base : cdi.customItems){
if (base instanceof CustomDropItem)
dropsCount++;
@@ -271,10 +269,9 @@ private void parseCustomDrops2(final List> itemConfigurations, final CustomDro
if ("overall_chance".equalsIgnoreCase(materialName)){
if (itemEntry.getValue() instanceof Double)
- dropInstance.overallChance = (Double) itemEntry.getValue();
+ dropInstance.overallChance = (float) itemEntry.getValue();
else if (itemEntry.getValue() instanceof Integer)
- dropInstance.overallChance = Double.valueOf((Integer) itemEntry.getValue());
-
+ dropInstance.overallChance = Float.valueOf((Integer) itemEntry.getValue());
continue;
}
else if ("overall_permission".equalsIgnoreCase(materialName)){
@@ -298,7 +295,7 @@ else if (itemEntry.getValue() instanceof ArrayList)
Utils.logger.warning("Did not find droptable id match for name: " + useEntityDropId);
else {
final CustomDropInstance refDrop = handler.customItemGroups.get(useEntityDropId);
- for (CustomDropBase itemDrop : refDrop.customItems)
+ for (final CustomDropBase itemDrop : refDrop.customItems)
dropInstance.customItems.add(itemDrop instanceof CustomDropItem ?
((CustomDropItem) itemDrop).cloneItem() :
((CustomCommand) itemDrop).cloneItem());
@@ -311,7 +308,7 @@ else if (itemEntry.getValue() instanceof ArrayList)
final ConfigurationSection itemInfoConfiguration = objectToConfigurationSection_old(itemEntry.getValue());
if (itemInfoConfiguration == null) continue;
- CustomDropBase dropBase;
+ final CustomDropBase dropBase;
if ("customCommand".equalsIgnoreCase(materialName))
dropBase = new CustomCommand(defaults);
else {
@@ -326,7 +323,7 @@ else if (itemEntry.getValue() instanceof ArrayList)
}
private void parseCustomDropsAttributes(@NotNull final CustomDropBase dropBase, @NotNull final ConfigurationSection cs, final @NotNull CustomDropInstance dropInstance){
- dropBase.chance = ymlHelper.getDouble(cs, "chance", this.defaults.chance);
+ dropBase.chance = ymlHelper.getFloat(cs, "chance", this.defaults.chance);
dropBase.permissions.addAll(this.defaults.permissions);
dropBase.permissions.addAll(ymlHelper.getStringSet(cs, "permission"));
dropBase.minLevel = ymlHelper.getInt(cs,"minlevel", this.defaults.minLevel);
@@ -347,7 +344,7 @@ private void parseCustomDropsAttributes(@NotNull final CustomDropBase dropBase,
}
if (!Utils.isNullOrEmpty(ymlHelper.getString(cs,"overall_chance"))) {
- dropInstance.overallChance = ymlHelper.getDouble(cs, "overall_chance");
+ dropInstance.overallChance = ymlHelper.getFloat(cs, "overall_chance");
if (dropInstance.overallChance == 0.0) dropInstance.overallChance = null;
}
@@ -377,6 +374,7 @@ else if (singleCommand != null)
checkEquippedChance(item, cs);
parseItemFlags(item, cs, dropInstance);
+ item.causeOfDeathReqs = buildCachedModalListOfDamageCause(cs, this.defaults.causeOfDeathReqs);
item.onlyDropIfEquipped = ymlHelper.getBoolean(cs, "only-drop-if-equipped", this.defaults.onlyDropIfEquipped);
item.priority = ymlHelper.getInt(cs,"priority", this.defaults.priority);
item.noMultiplier = ymlHelper.getBoolean(cs,"nomultiplier", this.defaults.noMultiplier);
@@ -387,7 +385,7 @@ else if (singleCommand != null)
if (mobHeadIdStr != null){
try {
item.customPlayerHeadId = UUID.fromString(mobHeadIdStr);
- } catch (Exception e) {
+ } catch (final Exception e) {
Utils.logger.warning("Invalid UUID: " + mobHeadIdStr);
}
}
@@ -403,7 +401,7 @@ else if (singleCommand != null)
item.customName = ymlHelper.getString(cs, "name", item.customName);
if (!Utils.isNullOrEmpty(ymlHelper.getString(cs,"excludemobs"))) {
- String[] excludes = Objects.requireNonNull(ymlHelper.getString(cs, "excludemobs")).split(";");
+ final String[] excludes = Objects.requireNonNull(ymlHelper.getString(cs, "excludemobs")).split(";");
item.excludedMobs.clear();
for (final String exclude : excludes)
item.excludedMobs.add(exclude.trim());
@@ -431,12 +429,78 @@ else if (singleCommand != null)
applyMetaAttributes(item);
}
+ @NotNull
+ private CachedModalList buildCachedModalListOfDamageCause(final ConfigurationSection cs,
+ final CachedModalList defaultValue) {
+ if (cs == null) return defaultValue;
+
+ final CachedModalList cachedModalList = new CachedModalList<>();
+ final Object simpleStringOrArray = cs.get(ymlHelper.getKeyNameFromConfig(cs, "cause-of-death"));
+ ConfigurationSection cs2 = null;
+ List useList = null;
+
+ if (simpleStringOrArray instanceof ArrayList)
+ useList = new LinkedList<>((ArrayList) simpleStringOrArray);
+ else if (simpleStringOrArray instanceof String)
+ useList = List.of((String) simpleStringOrArray);
+
+ if (useList == null) {
+ final String useKeyName = ymlHelper.getKeyNameFromConfig(cs, "cause-of-death");
+
+ cs2 = objTo_CS(cs, useKeyName);
+ }
+ if (cs2 == null && useList == null) return defaultValue;
+
+ cachedModalList.doMerge = ymlHelper.getBoolean(cs2, "merge");
+ if (cs2 != null) {
+ final String allowedList = ymlHelper.getKeyNameFromConfig(cs2, "allowed-list");
+ useList = YmlParsingHelper.getListFromConfigItem(cs2, allowedList);
+ }
+
+ for (final String item : useList){
+ if (item.trim().isEmpty()) continue;
+ if ("*".equals(item.trim())){
+ cachedModalList.allowAll = true;
+ continue;
+ }
+ try {
+ final EntityDamageEvent.DamageCause cause = EntityDamageEvent.DamageCause.valueOf(item.trim().toUpperCase());
+ cachedModalList.allowedList.add(cause);
+ } catch (final IllegalArgumentException ignored) {
+ Utils.logger.warning("Invalid damage cause: " + item);
+ }
+ }
+ if (cs2 == null) return cachedModalList;
+
+ final String excludedList = ymlHelper.getKeyNameFromConfig(cs2, "excluded-list");
+
+ for (final String item : YmlParsingHelper.getListFromConfigItem(cs2, excludedList)){
+ if (item.trim().isEmpty()) continue;
+ if ("*".equals(item.trim())){
+ cachedModalList.excludeAll = true;
+ continue;
+ }
+ try {
+ final EntityDamageEvent.DamageCause cause = EntityDamageEvent.DamageCause.valueOf(item.trim().toUpperCase());
+ cachedModalList.excludedList.add(cause);
+ } catch (final IllegalArgumentException ignored) {
+ Utils.logger.warning("Invalid damage cause: " + item);
+ }
+ }
+
+ if (cachedModalList.isEmpty() && !cachedModalList.allowAll && !cachedModalList.excludeAll)
+ return defaultValue;
+
+ return cachedModalList;
+ }
+
private void parseEnchantments(final ConfigurationSection cs, final CustomDropItem item){
if (cs == null) return;
final Map enchantMap = cs.getValues(false);
- for (final String enchantName : enchantMap.keySet()) {
- final Object value = enchantMap.get(enchantName);
+ for (final Map.Entry enchants : enchantMap.entrySet()) {
+ final String enchantName = enchants.getKey();
+ final Object value = enchants.getValue();
int enchantLevel = 1;
if (value != null && Utils.isInteger(value.toString()))
@@ -444,8 +508,8 @@ private void parseEnchantments(final ConfigurationSection cs, final CustomDropIt
final Enchantment en = Enchantment.getByKey(NamespacedKey.minecraft(enchantName.toLowerCase()));
if (en != null) {
- if (item.getMaterial().equals(Material.ENCHANTED_BOOK)) {
- EnchantmentStorageMeta meta = (EnchantmentStorageMeta) item.getItemStack().getItemMeta();
+ if (item.getMaterial() == Material.ENCHANTED_BOOK) {
+ final EnchantmentStorageMeta meta = (EnchantmentStorageMeta) item.getItemStack().getItemMeta();
if (meta != null) {
meta.addStoredEnchant(en, enchantLevel, true);
item.getItemStack().setItemMeta(meta);
@@ -476,13 +540,21 @@ private void applyMetaAttributes(@NotNull final CustomDropItem item){
boolean madeChanges = false;
if (item.lore != null && !item.lore.isEmpty()){
- meta.setLore(Utils.colorizeAllInList(item.lore));
+ if (VersionUtils.isRunningPaper())
+ PaperUtils.updateItemMetaLore(meta, item.lore);
+ else
+ SpigotUtils.updateItemMetaLore(meta, item.lore);
+
item.getItemStack().setItemMeta(meta);
madeChanges = true;
}
- if (item.customName != null && !"".equals(item.customName)){
- meta.setDisplayName(MessageUtils.colorizeAll(item.customName));
+ if (item.customName != null && !item.customName.isEmpty()){
+ if (VersionUtils.isRunningPaper())
+ PaperUtils.updateItemDisplayName(meta, item.customName);
+ else
+ SpigotUtils.updateItemDisplayName(meta, item.customName);
+
item.getItemStack().setItemMeta(meta);
madeChanges = true;
}
@@ -507,7 +579,7 @@ private void applyMetaAttributes(@NotNull final CustomDropItem item){
private void parseItemFlags(final CustomDropItem item, final ConfigurationSection cs, final CustomDropInstance dropInstance){
if (cs == null) return;
- List flagList = cs.getStringList(ymlHelper.getKeyNameFromConfig(cs, "item_flags"));
+ final List flagList = cs.getStringList(ymlHelper.getKeyNameFromConfig(cs, "item_flags"));
String itemFlags = null;
if (flagList.isEmpty()) {
@@ -523,9 +595,9 @@ private void parseItemFlags(final CustomDropItem item, final ConfigurationSectio
for (final String flag : flagsToParse){
try {
- ItemFlag newFlag = ItemFlag.valueOf(flag.trim().toUpperCase());
+ final ItemFlag newFlag = ItemFlag.valueOf(flag.trim().toUpperCase());
results.add(newFlag);
- } catch (Exception e) {
+ } catch (final Exception e) {
Utils.logger.warning(String.format("Invalid itemflag: %s, item: %s, mobOrGroup: %s",
flag, item.getMaterial().name(), dropInstance.getMobOrGroupName()));
}
@@ -539,14 +611,14 @@ private void checkEquippedChance(final CustomDropItem item, @NotNull final Confi
if (Utils.isNullOrEmpty(temp)) return;
if ("false".equalsIgnoreCase(temp)) {
- item.equippedSpawnChance = 0.0;
+ item.equippedSpawnChance = 0.0F;
return;
} else if ("true".equalsIgnoreCase(temp)) {
- item.equippedSpawnChance = 1.0;
+ item.equippedSpawnChance = 1.0F;
return;
}
- item.equippedSpawnChance = ymlHelper.getDouble(cs,"equipped", this.defaults.equippedSpawnChance);
+ item.equippedSpawnChance = ymlHelper.getFloat(cs,"equipped", this.defaults.equippedSpawnChance);
}
@Nullable
@@ -592,10 +664,10 @@ private boolean addMaterialToDrop(String materialName, final CustomDropInstance
materialName = Utils.replaceEx(materialName, "mob_head", "player_head");
materialName = Utils.replaceEx(materialName, "mobhead", "player_head");
- Material material;
+ final Material material;
try {
material = Material.valueOf(materialName.toUpperCase());
- } catch (Exception e) {
+ } catch (final Exception e) {
Utils.logger.warning(String.format("Invalid material type specified in customdrops.yml for: %s, %s", dropInstance.getMobOrGroupName(), materialName));
return false;
}
@@ -658,13 +730,13 @@ private void showCustomDropsDebugInfo(final StringBuilder sbMain){
}
}
- for (final String group : handler.customDropsitems_groups.keySet()) {
- final CustomDropInstance dropInstance = handler.customDropsitems_groups.get(group);
+ for (final Map.Entry customDrops : handler.customDropsitems_groups.entrySet()) {
+ final CustomDropInstance dropInstance = customDrops.getValue();
final String override = dropInstance.overrideStockDrops ? " (override)" : "";
final String overallChance = dropInstance.overallChance != null ? " (overall_chance: " + dropInstance.overallChance + ")" : "";
if (sbMain.length() > 0) sbMain.append(System.lineSeparator());
sbMain.append("group: ");
- sbMain.append(group);
+ sbMain.append(customDrops.getKey());
sbMain.append(override);
sbMain.append(overallChance);
for (final CustomDropBase baseItem : dropInstance.customItems) {
@@ -721,6 +793,11 @@ private void showCustomDropsDebugInfo(final StringBuilder sbMain){
if (baseItem.noSpawner) sb.append(", nospn");
+ if (baseItem.causeOfDeathReqs != null){
+ sb.append(", ");
+ sb.append(baseItem.causeOfDeathReqs);
+ }
+
if (!Utils.isNullOrEmpty(baseItem.groupId)) {
sb.append(", gId: &b");
sb.append(baseItem.groupId);
@@ -751,7 +828,7 @@ private void showCustomDropsDebugInfo(final StringBuilder sbMain){
if (item.noMultiplier) sb.append(", nomultp");
if (item.lore != null && !item.lore.isEmpty()) sb.append(", hasLore");
- if (item.customName != null && !"".equals(item.customName)) sb.append(", hasName");
+ if (item.customName != null && !item.customName.isEmpty()) sb.append(", hasName");
if (item.getDamage() != 0 || item.getHasDamageRange()) {
sb.append(", dmg: &b");
sb.append(item.getDamageAsString());
@@ -774,7 +851,6 @@ private void showCustomDropsDebugInfo(final StringBuilder sbMain){
final ItemMeta meta = item.getItemStack().getItemMeta();
final StringBuilder sb2 = new StringBuilder();
if (meta != null) {
- boolean isFirst = true;
for (final Enchantment enchant : meta.getEnchants().keySet()) {
if (sb2.length() > 0) sb.append(", ");
sb2.append(String.format("&b%s&r (%s)", enchant.getKey().getKey(), item.getItemStack().getItemMeta().getEnchants().get(enchant)));
@@ -789,4 +865,26 @@ private void showCustomDropsDebugInfo(final StringBuilder sbMain){
return sb.toString();
}
+
+ @Nullable
+ private ConfigurationSection objTo_CS(final ConfigurationSection cs, final String path){
+ if (cs == null) return null;
+ final String useKey = ymlHelper.getKeyNameFromConfig(cs, path);
+ final Object object = cs.get(useKey);
+
+ if (object == null) return null;
+
+ if (object instanceof ConfigurationSection) {
+ return (ConfigurationSection) object;
+ } else if (object instanceof Map) {
+ final MemoryConfiguration result = new MemoryConfiguration();
+ result.addDefaults((Map) object);
+ return result.getDefaultSection();
+ } else {
+ final String currentPath = Utils.isNullOrEmpty(cs.getCurrentPath()) ?
+ path : cs.getCurrentPath() + "." + path;
+ Utils.logger.warning(currentPath + ": couldn't parse Config of type: " + object.getClass().getSimpleName() + ", value: " + object);
+ return null;
+ }
+ }
}
diff --git a/src/main/java/me/lokka30/levelledmobs/events/MobPostLevelEvent.java b/src/main/java/me/lokka30/levelledmobs/events/MobPostLevelEvent.java
index 2fd9e9344..2f695027f 100644
--- a/src/main/java/me/lokka30/levelledmobs/events/MobPostLevelEvent.java
+++ b/src/main/java/me/lokka30/levelledmobs/events/MobPostLevelEvent.java
@@ -22,12 +22,13 @@
* @author lokka30
* @since 2.5.0
*/
+@SuppressWarnings("unused")
public class MobPostLevelEvent extends Event {
private static final HandlerList HANDLERS = new HandlerList();
@Override
- public HandlerList getHandlers() {
+ public @NotNull HandlerList getHandlers() {
return HANDLERS;
}
diff --git a/src/main/java/me/lokka30/levelledmobs/events/MobPreLevelEvent.java b/src/main/java/me/lokka30/levelledmobs/events/MobPreLevelEvent.java
index c81e01ce6..07272f85e 100644
--- a/src/main/java/me/lokka30/levelledmobs/events/MobPreLevelEvent.java
+++ b/src/main/java/me/lokka30/levelledmobs/events/MobPreLevelEvent.java
@@ -25,12 +25,13 @@
* @author lokka30
* @since 2.5.0
*/
+@SuppressWarnings("unused")
public class MobPreLevelEvent extends Event implements Cancellable {
private static final HandlerList HANDLERS = new HandlerList();
@Override
- public HandlerList getHandlers() {
+ public @NotNull HandlerList getHandlers() {
return HANDLERS;
}
@@ -46,7 +47,7 @@ public boolean isCancelled() {
}
@Override
- public void setCancelled(boolean cancelled) {
+ public void setCancelled(final boolean cancelled) {
this.cancelled = cancelled;
}
@@ -94,7 +95,7 @@ public HashSet getAdditionalInformation() {
return additionalInformation;
}
- public void setLevel(int level) {
+ public void setLevel(final int level) {
this.level = level;
}
diff --git a/src/main/java/me/lokka30/levelledmobs/events/SummonedMobPreLevelEvent.java b/src/main/java/me/lokka30/levelledmobs/events/SummonedMobPreLevelEvent.java
index 4118ee1a5..d0ef8d8dd 100644
--- a/src/main/java/me/lokka30/levelledmobs/events/SummonedMobPreLevelEvent.java
+++ b/src/main/java/me/lokka30/levelledmobs/events/SummonedMobPreLevelEvent.java
@@ -9,6 +9,7 @@
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.NotNull;
/**
* This event is fired *before* a mob has
@@ -18,12 +19,13 @@
* @author lokka30
* @since 2.5.0
*/
+@SuppressWarnings("unused")
public class SummonedMobPreLevelEvent extends Event implements Cancellable {
private static final HandlerList HANDLERS = new HandlerList();
@Override
- public HandlerList getHandlers() {
+ public @NotNull HandlerList getHandlers() {
return HANDLERS;
}
@@ -39,14 +41,14 @@ public boolean isCancelled() {
}
@Override
- public void setCancelled(boolean cancelled) {
+ public void setCancelled(final boolean cancelled) {
this.cancelled = cancelled;
}
private final LivingEntity entity;
private int level;
- public SummonedMobPreLevelEvent(LivingEntity entity, int level) {
+ public SummonedMobPreLevelEvent(final LivingEntity entity, final int level) {
super(!Bukkit.isPrimaryThread());
this.entity = entity;
this.level = level;
@@ -60,7 +62,7 @@ public int getLevel() {
return level;
}
- public void setLevel(int level) {
+ public void setLevel(final int level) {
this.level = level;
}
}
diff --git a/src/main/java/me/lokka30/levelledmobs/listeners/BlockPlaceListener.java b/src/main/java/me/lokka30/levelledmobs/listeners/BlockPlaceListener.java
index 7e2f719e7..1b6bccca1 100644
--- a/src/main/java/me/lokka30/levelledmobs/listeners/BlockPlaceListener.java
+++ b/src/main/java/me/lokka30/levelledmobs/listeners/BlockPlaceListener.java
@@ -40,8 +40,8 @@ public BlockPlaceListener(final LevelledMobs main) {
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onBlockPlaceEvent(@NotNull final BlockPlaceEvent event) {
- if (!event.getBlockPlaced().getType().equals(Material.SPAWNER) ||
- !event.getItemInHand().getType().equals(Material.SPAWNER))
+ if (event.getBlockPlaced().getType() != Material.SPAWNER ||
+ event.getItemInHand().getType() != Material.SPAWNER)
return;
processMobSpawner(event.getItemInHand(), event.getBlockPlaced());
@@ -97,8 +97,14 @@ else if (valueInt != null) {
switch (i){
case 6: cs.setDelay(valueInt); break;
case 7: cs.setMaxNearbyEntities(valueInt); break;
- case 8: cs.setMinSpawnDelay(valueInt); break;
- case 9: cs.setMaxSpawnDelay(valueInt); break;
+ case 8:
+ if (cs.getMaxSpawnDelay() < valueInt)
+ cs.setMaxSpawnDelay(valueInt);
+ cs.setMinSpawnDelay(valueInt); break;
+ case 9:
+ if (cs.getMinSpawnDelay() > valueInt)
+ cs.setMinSpawnDelay(valueInt);
+ cs.setMaxSpawnDelay(valueInt); break;
case 10: cs.setRequiredPlayerRange(valueInt); break;
case 11: cs.setSpawnCount(valueInt); break;
case 12: cs.setSpawnRange(valueInt); break;
diff --git a/src/main/java/me/lokka30/levelledmobs/listeners/CombustListener.java b/src/main/java/me/lokka30/levelledmobs/listeners/CombustListener.java
index 077a76aac..6eb119b51 100644
--- a/src/main/java/me/lokka30/levelledmobs/listeners/CombustListener.java
+++ b/src/main/java/me/lokka30/levelledmobs/listeners/CombustListener.java
@@ -40,8 +40,8 @@ public CombustListener(final LevelledMobs main){
public void onCombust(final EntityCombustEvent event) {
if (event instanceof EntityCombustByBlockEvent || event instanceof EntityCombustByEntityEvent) return;
- if (event.getEntity().getWorld().getEnvironment().equals(World.Environment.NETHER) ||
- event.getEntity().getWorld().getEnvironment().equals(World.Environment.THE_END))
+ if (event.getEntity().getWorld().getEnvironment() == World.Environment.NETHER ||
+ event.getEntity().getWorld().getEnvironment() == World.Environment.THE_END)
return;
final List entityTypesCanBurnInSunlight2 = Arrays.asList(
@@ -58,7 +58,7 @@ public void onCombust(final EntityCombustEvent event) {
}
final LivingEntityWrapper lmEntity = LivingEntityWrapper.getInstance((LivingEntity) event.getEntity(), main);
- double multiplier = main.rulesManager.getRule_SunlightBurnIntensity(lmEntity);
+ final double multiplier = main.rulesManager.getRule_SunlightBurnIntensity(lmEntity);
if (multiplier == 0.0) {
lmEntity.free();
return;
diff --git a/src/main/java/me/lokka30/levelledmobs/listeners/EntityDamageDebugListener.java b/src/main/java/me/lokka30/levelledmobs/listeners/EntityDamageDebugListener.java
index 10ce0f651..036444e1f 100644
--- a/src/main/java/me/lokka30/levelledmobs/listeners/EntityDamageDebugListener.java
+++ b/src/main/java/me/lokka30/levelledmobs/listeners/EntityDamageDebugListener.java
@@ -8,7 +8,7 @@
import me.lokka30.levelledmobs.misc.Cooldown;
import me.lokka30.levelledmobs.misc.LivingEntityWrapper;
import me.lokka30.levelledmobs.misc.Utils;
-import me.lokka30.microlib.MessageUtils;
+import me.lokka30.microlib.messaging.MessageUtils;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.attribute.AttributeModifier;
@@ -65,7 +65,7 @@ private void checkEntity(final Player player, final @NotNull LivingEntityWrapper
// Don't spam the player's chat
final String entityId = Integer.toString(lmEntity.getLivingEntity().getEntityId());
if (cooldownMap.containsKey(player.getUniqueId())) {
- Cooldown cooldown = cooldownMap.get(player.getUniqueId());
+ final Cooldown cooldown = cooldownMap.get(player.getUniqueId());
if (cooldown.doesCooldownBelongToIdentifier(entityId)) {
if (!cooldown.hasCooldownExpired(2)) return;
@@ -103,7 +103,7 @@ private void checkEntity(final Player player, final @NotNull LivingEntityWrapper
for (final AttributeModifier mod : attributeInstance.getModifiers()){
if (count == 0) sb.append(" (");
else sb.append(", ");
- if (mod.getOperation().equals(AttributeModifier.Operation.MULTIPLY_SCALAR_1))
+ if (mod.getOperation() == AttributeModifier.Operation.MULTIPLY_SCALAR_1)
sb.append("* ");
else
sb.append("+ ");
diff --git a/src/main/java/me/lokka30/levelledmobs/listeners/EntityDeathListener.java b/src/main/java/me/lokka30/levelledmobs/listeners/EntityDeathListener.java
index 3df2cfc27..2eb137a52 100644
--- a/src/main/java/me/lokka30/levelledmobs/listeners/EntityDeathListener.java
+++ b/src/main/java/me/lokka30/levelledmobs/listeners/EntityDeathListener.java
@@ -36,7 +36,7 @@ public EntityDeathListener(final LevelledMobs main) {
}
// These entities will be forced not to have levelled drops
- final HashSet bypassDrops = new HashSet<>(Arrays.asList("ARMOR_STAND", "ITEM_FRAME", "DROPPED_ITEM", "PAINTING"));
+ private final HashSet bypassDrops = new HashSet<>(Arrays.asList("ARMOR_STAND", "ITEM_FRAME", "DROPPED_ITEM", "PAINTING"));
@EventHandler(ignoreCancelled = true, priority = EventPriority.NORMAL)
public void onDeath(@NotNull final EntityDeathEvent event) {
diff --git a/src/main/java/me/lokka30/levelledmobs/listeners/EntitySpawnListener.java b/src/main/java/me/lokka30/levelledmobs/listeners/EntitySpawnListener.java
index 3f9038cdc..b5be60f9c 100644
--- a/src/main/java/me/lokka30/levelledmobs/listeners/EntitySpawnListener.java
+++ b/src/main/java/me/lokka30/levelledmobs/listeners/EntitySpawnListener.java
@@ -6,6 +6,7 @@
import me.lokka30.levelledmobs.LevelledMobs;
import me.lokka30.levelledmobs.managers.ExternalCompatibilityManager;
+import me.lokka30.levelledmobs.managers.LevelManager;
import me.lokka30.levelledmobs.misc.*;
import me.lokka30.levelledmobs.rules.LevelledMobSpawnReason;
import me.lokka30.levelledmobs.rules.NametagVisibilityEnum;
@@ -53,16 +54,19 @@ public void onEntitySpawn(@NotNull final EntitySpawnEvent event) {
final LivingEntityWrapper lmEntity = LivingEntityWrapper.getInstance((LivingEntity) event.getEntity(), main);
- if (event instanceof CreatureSpawnEvent && ((CreatureSpawnEvent) event).getSpawnReason().equals(CreatureSpawnEvent.SpawnReason.CUSTOM) &&
- !lmEntity.isLevelled()) {
+ if (event instanceof CreatureSpawnEvent) {
+ final CreatureSpawnEvent.SpawnReason spawnReason = ((CreatureSpawnEvent) event).getSpawnReason();
- lmEntity.setSpawnReason(LevelledMobSpawnReason.CUSTOM);
- if (main.configUtils.playerLevellingEnabled && lmEntity.getPlayerForLevelling() == null)
- updateMobForPlayerLevelling(lmEntity);
+ lmEntity.setSpawnReason(adaptVanillaSpawnReason(spawnReason));
+ if ((spawnReason == CreatureSpawnEvent.SpawnReason.CUSTOM || spawnReason == CreatureSpawnEvent.SpawnReason.SPAWNER_EGG) &&
+ !lmEntity.isLevelled()) {
+ if (main.configUtils.playerLevellingEnabled && lmEntity.getPlayerForLevelling() == null)
+ updateMobForPlayerLevelling(lmEntity);
- delayedAddToQueue(lmEntity, event, 20);
- lmEntity.free();
- return;
+ delayedAddToQueue(lmEntity, event, 20);
+ lmEntity.free();
+ return;
+ }
}
if (!processMobSpawns) {
@@ -127,7 +131,7 @@ private static List getPlayersOnServerNearMob(final @NotNull LivingEntit
return mob.getWorld().getPlayers().stream()
.filter(p -> mob.getWorld().equals(p.getWorld()))
- .filter(p -> !p.getGameMode().equals(GameMode.SPECTATOR))
+ .filter(p -> p.getGameMode() != GameMode.SPECTATOR)
.map(p -> Map.entry(mob.getLocation().distanceSquared(p.getLocation()), p))
.filter(e -> e.getKey() <= maxDistanceSquared)
.sorted(Comparator.comparingDouble(Map.Entry::getKey))
@@ -139,7 +143,7 @@ private static List getPlayersOnServerNearMob(final @NotNull LivingEntit
public static List getPlayersNearMob(final @NotNull LivingEntity mob, final int checkDistance){
return mob.getNearbyEntities(checkDistance, checkDistance, checkDistance).stream()
.filter(e -> e instanceof org.bukkit.entity.Player)
- .filter(e -> !((org.bukkit.entity.Player) e).getGameMode().equals(GameMode.SPECTATOR))
+ .filter(e -> ((Player) e).getGameMode() != GameMode.SPECTATOR)
.map(e -> Map.entry(mob.getLocation().distanceSquared(e.getLocation()), (org.bukkit.entity.Player) e))
.sorted(Comparator.comparingDouble(Map.Entry::getKey))
.map(Map.Entry::getValue)
@@ -206,7 +210,7 @@ public void run() {
world.spawnParticle(Particle.SOUL, location, 20, 0, 0, 0, 0.1);
Thread.sleep(50);
}
- } catch (InterruptedException ignored) { }
+ } catch (final InterruptedException ignored) { }
}
};
@@ -219,7 +223,6 @@ public void preprocessMob(final @NotNull LivingEntityWrapper lmEntity, @NotNull
return;
if (lmEntity.getLivingEntity() == null) return;
- LevelledMobSpawnReason spawnReason = LevelledMobSpawnReason.DEFAULT;
AdditionalLevelInformation additionalInfo = AdditionalLevelInformation.NOT_APPLICABLE;
lmEntity.setSpawnedTimeOfDay((int) lmEntity.getWorld().getTime());
@@ -234,22 +237,25 @@ public void preprocessMob(final @NotNull LivingEntityWrapper lmEntity, @NotNull
}
Utils.debugLog(main, DebugType.MOB_SPAWNER, "Spawned mob from vanilla spawner: &b" + spawnEvent.getEntityType());
- spawnReason = LevelledMobSpawnReason.SPAWNER;
} else if (event instanceof CreatureSpawnEvent) {
final CreatureSpawnEvent spawnEvent = (CreatureSpawnEvent) event;
- if (spawnEvent.getSpawnReason().equals(CreatureSpawnEvent.SpawnReason.SPAWNER) ||
- spawnEvent.getSpawnReason().equals(CreatureSpawnEvent.SpawnReason.SLIME_SPLIT))
+ if (spawnEvent.getSpawnReason() == CreatureSpawnEvent.SpawnReason.SPAWNER ||
+ spawnEvent.getSpawnReason() == CreatureSpawnEvent.SpawnReason.SLIME_SPLIT)
return;
- if (spawnEvent.getSpawnReason().equals(CreatureSpawnEvent.SpawnReason.CUSTOM) &&
- main.levelManager.summonedEntityType.equals(lmEntity.getEntityType()) &&
- areLocationsTheSame(main.levelManager.summonedLocation, lmEntity.getLocation())) {
- // the mob was spawned by the summon command and will get processed directly
- return;
+ if (spawnEvent.getSpawnReason() == CreatureSpawnEvent.SpawnReason.CUSTOM ||
+ spawnEvent.getSpawnReason() == CreatureSpawnEvent.SpawnReason.SPAWNER_EGG) {
+ synchronized (LevelManager.summonedOrSpawnEggs_Lock){
+ if (main.levelManager.summonedOrSpawnEggs.containsKey(lmEntity.getLivingEntity())) {
+ // the mob was spawned by the summon command and will get processed directly
+ return;
+ }
+ }
}
- spawnReason = adaptVanillaSpawnReason(spawnEvent.getSpawnReason());
+ if (!lmEntity.reEvaluateLevel)
+ lmEntity.setSpawnReason(adaptVanillaSpawnReason(spawnEvent.getSpawnReason()));
} else if (event instanceof ChunkLoadEvent)
additionalInfo = AdditionalLevelInformation.FROM_CHUNK_LISTENER;
@@ -264,21 +270,28 @@ public void preprocessMob(final @NotNull LivingEntityWrapper lmEntity, @NotNull
final HashSet additionalLevelInfo = new HashSet<>(Collections.singletonList(additionalInfo));
final LevellableState levellableState = getLevellableState(lmEntity, event);
if (levellableState == LevellableState.ALLOWED) {
- if (lmEntity.reEvaluateLevel && main.configUtils.playerLevellingEnabled) {
- final Object syncObj = new Object();
- final BukkitRunnable runnable = new BukkitRunnable() {
- @Override
- public void run() {
- updateMobForPlayerLevelling(lmEntity);
- lmEntity.free();
- }
- };
- lmEntity.inUseCount.getAndIncrement();
- runnable.runTask(main);
+ final int levelAssignment = main.levelInterface.generateLevel(lmEntity);
+ if (shouldDenyLevel(lmEntity, levelAssignment)){
+ Utils.debugLog(main, DebugType.PLAYER_LEVELLING, String.format(
+ "Entity &b%s (lvl %s)&r denied relevelling to &b%s&r due to decrease-level disabled",
+ lmEntity.getNameIfBaby(), lmEntity.getMobLevel(), levelAssignment));
}
+ else {
+ if (lmEntity.reEvaluateLevel && main.configUtils.playerLevellingEnabled) {
+ final BukkitRunnable runnable = new BukkitRunnable() {
+ @Override
+ public void run() {
+ updateMobForPlayerLevelling(lmEntity);
+ lmEntity.free();
+ }
+ };
+ lmEntity.inUseCount.getAndIncrement();
+ runnable.runTask(main);
+ }
- main.levelInterface.applyLevelToMob(lmEntity, main.levelInterface.generateLevel(lmEntity),
- false, false, additionalLevelInfo);
+ main.levelInterface.applyLevelToMob(lmEntity, levelAssignment,
+ false, false, additionalLevelInfo);
+ }
} else {
Utils.debugLog(main, DebugType.APPLY_LEVEL_FAIL, "Entity &b" + lmEntity.getNameIfBaby() + "&7 in wo" +
"rld&b " + lmEntity.getWorldName() + "&7 was not levelled -> levellable state: &b" + levellableState);
@@ -298,27 +311,36 @@ else if (lmEntity.isBabyMob()) {
}
}
- private static boolean areLocationsTheSame(final Location location1, final Location location2){
- if (location1 == null || location2 == null) return false;
- if (location1.getWorld() == null || location2.getWorld() == null) return false;
+ private static boolean shouldDenyLevel(final @NotNull LivingEntityWrapper lmEntity, final int levelAssignment){
+ final boolean result =
+ lmEntity.reEvaluateLevel &&
+ !lmEntity.isRulesForceAll &&
+ lmEntity.playerLevellingAllowDecrease != null &&
+ !lmEntity.playerLevellingAllowDecrease &&
+ lmEntity.isLevelled() &&
+ levelAssignment < lmEntity.getMobLevel();
+
+ if (!result && lmEntity.pendingPlayerIdToSet != null) {
+ synchronized (lmEntity.getLivingEntity().getPersistentDataContainer()) {
+ lmEntity.getPDC().set(lmEntity.getMainInstance().namespaced_keys.playerLevelling_Id, PersistentDataType.STRING, lmEntity.pendingPlayerIdToSet);
+ }
+ }
- return location1.getBlockX() == location2.getBlockX() &&
- location1.getBlockY() == location2.getBlockY() &&
- location1.getBlockZ() == location2.getBlockZ();
+ return result;
}
@NotNull
private LevellableState getLevellableState(final LivingEntityWrapper lmEntity, @NotNull final Event event) {
- LevellableState levellableState = main.levelInterface.getLevellableState(lmEntity);
+ final LevellableState levellableState = main.levelInterface.getLevellableState(lmEntity);
if (levellableState != LevellableState.ALLOWED)
return levellableState;
if (event instanceof CreatureSpawnEvent) {
- CreatureSpawnEvent creatureSpawnEvent = (CreatureSpawnEvent) event;
+ final CreatureSpawnEvent creatureSpawnEvent = (CreatureSpawnEvent) event;
// the mob gets processed via SpawnerSpawnEvent
- if (((CreatureSpawnEvent) event).getSpawnReason().equals(CreatureSpawnEvent.SpawnReason.SPAWNER))
+ if (((CreatureSpawnEvent) event).getSpawnReason() == CreatureSpawnEvent.SpawnReason.SPAWNER)
return LevellableState.DENIED_OTHER;
Utils.debugLog(main, DebugType.ENTITY_SPAWN, "instanceof CreatureSpawnListener: &b" + creatureSpawnEvent.getEntityType() + "&7, with spawnReason &b" + creatureSpawnEvent.getSpawnReason() + "&7.");
diff --git a/src/main/java/me/lokka30/levelledmobs/listeners/PlayerDeathListener.java b/src/main/java/me/lokka30/levelledmobs/listeners/PlayerDeathListener.java
index 6bf568980..cbde26b45 100644
--- a/src/main/java/me/lokka30/levelledmobs/listeners/PlayerDeathListener.java
+++ b/src/main/java/me/lokka30/levelledmobs/listeners/PlayerDeathListener.java
@@ -6,19 +6,13 @@
import me.lokka30.levelledmobs.LevelledMobs;
import me.lokka30.levelledmobs.misc.LivingEntityWrapper;
-import me.lokka30.levelledmobs.misc.Utils;
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.LivingEntity;
-import org.bukkit.entity.Player;
-import org.bukkit.entity.Projectile;
+import me.lokka30.levelledmobs.misc.SpigotUtils;
+import me.lokka30.microlib.other.VersionUtils;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
-import org.bukkit.event.entity.EntityDamageByEntityEvent;
-import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
/**
* Listens for when a player dies
@@ -28,11 +22,14 @@
*/
public class PlayerDeathListener implements Listener {
- public PlayerDeathListener(final LevelledMobs main){
+ public PlayerDeathListener(final LevelledMobs main) {
this.main = main;
+ if (VersionUtils.isRunningPaper())
+ paperListener = new me.lokka30.levelledmobs.listeners.paper.PlayerDeathListener(main);
}
final private LevelledMobs main;
+ private me.lokka30.levelledmobs.listeners.paper.PlayerDeathListener paperListener;
/**
* This listener handles death nametags so we can determine which mob killed
@@ -42,7 +39,14 @@ public PlayerDeathListener(final LevelledMobs main){
*/
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onPlayerDeath(@NotNull final PlayerDeathEvent event) {
- final LivingEntityWrapper lmEntity = getPlayersKiller(event);
+ // returns false if not a translatable component, in which case just use the old method
+ // this can happen if another plugin has buthered the event by using the deprecated method (*cough* mythic mobs)
+ if (!VersionUtils.isRunningPaper() || !paperListener.onPlayerDeathEvent(event))
+ nonPaper_PlayerDeath(event);
+ }
+
+ private void nonPaper_PlayerDeath(@NotNull final PlayerDeathEvent event){
+ final LivingEntityWrapper lmEntity = SpigotUtils.getPlayersKiller(event, main);
if (main.placeholderApiIntegration != null){
main.placeholderApiIntegration.putPlayerOrMobDeath(event.getEntity(), lmEntity);
@@ -52,36 +56,4 @@ public void onPlayerDeath(@NotNull final PlayerDeathEvent event) {
if (lmEntity != null)
lmEntity.free();
}
-
- @Nullable
- private LivingEntityWrapper getPlayersKiller(@NotNull final PlayerDeathEvent event){
- if (event.getDeathMessage() == null) return null;
-
- final EntityDamageEvent entityDamageEvent = event.getEntity().getLastDamageCause();
- if (entityDamageEvent == null || entityDamageEvent.isCancelled() || !(entityDamageEvent instanceof EntityDamageByEntityEvent))
- return null;
-
- final Entity damager = ((EntityDamageByEntityEvent) entityDamageEvent).getDamager();
- LivingEntity killer;
-
- if (damager instanceof Projectile)
- killer = (LivingEntity) ((Projectile) damager).getShooter();
- else if (!(damager instanceof LivingEntity))
- return null;
- else
- killer = (LivingEntity) damager;
-
- if (killer == null || Utils.isNullOrEmpty(killer.getName()) || killer instanceof Player) return null;
-
- final LivingEntityWrapper lmKiller = LivingEntityWrapper.getInstance(killer, main);
- if (!lmKiller.isLevelled())
- return lmKiller;
-
- final String deathMessage = main.levelManager.getNametag(lmKiller, true);
- if (Utils.isNullOrEmpty(deathMessage) || "disabled".equalsIgnoreCase(deathMessage))
- return lmKiller;
-
- event.setDeathMessage(Utils.replaceEx(event.getDeathMessage(), killer.getName(), deathMessage));
- return lmKiller;
- }
}
diff --git a/src/main/java/me/lokka30/levelledmobs/listeners/PlayerInteractEventListener.java b/src/main/java/me/lokka30/levelledmobs/listeners/PlayerInteractEventListener.java
index 068527c75..48ee3c999 100644
--- a/src/main/java/me/lokka30/levelledmobs/listeners/PlayerInteractEventListener.java
+++ b/src/main/java/me/lokka30/levelledmobs/listeners/PlayerInteractEventListener.java
@@ -5,59 +5,80 @@
package me.lokka30.levelledmobs.listeners;
import me.lokka30.levelledmobs.LevelledMobs;
+import me.lokka30.levelledmobs.commands.MessagesBase;
+import me.lokka30.levelledmobs.commands.subcommands.SpawnerBaseClass;
import me.lokka30.levelledmobs.commands.subcommands.SpawnerSubCommand;
+import me.lokka30.levelledmobs.managers.LevelManager;
+import me.lokka30.levelledmobs.misc.AdditionalLevelInformation;
import me.lokka30.levelledmobs.misc.Cooldown;
+import me.lokka30.levelledmobs.misc.LivingEntityWrapper;
import me.lokka30.levelledmobs.misc.Point;
import me.lokka30.levelledmobs.misc.Utils;
-import me.lokka30.microlib.MessageUtils;
+import me.lokka30.microlib.messaging.MessageUtils;
+import me.lokka30.microlib.other.VersionUtils;
+
+import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.block.CreatureSpawner;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
+import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot;
+import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import java.util.Collections;
import java.util.HashMap;
-import java.util.List;
+import java.util.HashSet;
import java.util.UUID;
+import java.util.concurrent.ThreadLocalRandom;
/**
* Listens for when a player interacts with the environment.
- * Currently only used to check for LM spawners
+ * Currently only used to check for LM spawners and LM spawn eggs
*
* @author stumper66
* @since 3.1.2
*/
-public class PlayerInteractEventListener implements Listener {
-
- final private LevelledMobs main;
-
+public class PlayerInteractEventListener extends MessagesBase implements Listener {
public PlayerInteractEventListener(final LevelledMobs main) {
- this.main = main;
+ super(main);
}
private final HashMap cooldownMap = new HashMap<>();
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
- void onPlayerInteractEvent(final PlayerInteractEvent event) {
+ void onPlayerInteractEvent(final @NotNull PlayerInteractEvent event) {
+ if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
+
+ commandSender = event.getPlayer();
+ messageLabel = "lm";
+
+ if (event.getMaterial().name().toLowerCase().endsWith("_spawn_egg")){
+ if (processLMSpawnEgg(event)) return;
+ }
+
if (main.companion.spawner_InfoIds.isEmpty() && main.companion.spawner_CopyIds.isEmpty()) return;
- if (event.getHand() == null || !event.getHand().equals(EquipmentSlot.HAND)) return;
- if (!event.getAction().equals(Action.RIGHT_CLICK_BLOCK)) return;
+ if (event.getHand() == null || event.getHand() != EquipmentSlot.HAND) return;
final boolean doShowInfo = main.companion.spawner_InfoIds.contains(event.getPlayer().getUniqueId());
final boolean doCopy = main.companion.spawner_CopyIds.contains(event.getPlayer().getUniqueId());
if (!doCopy && !doShowInfo) return;
- if (event.getClickedBlock() == null || !event.getClickedBlock().getType().equals(Material.SPAWNER))
+ if (event.getClickedBlock() == null || event.getClickedBlock().getType() != Material.SPAWNER)
return;
final UUID uuid = event.getPlayer().getUniqueId();
@@ -73,21 +94,141 @@ void onPlayerInteractEvent(final PlayerInteractEvent event) {
final CreatureSpawner cs = (CreatureSpawner) event.getClickedBlock().getState();
if (doShowInfo)
showInfo(event.getPlayer(), cs);
- else if (event.getMaterial().equals(Material.AIR))
+ else if (event.getMaterial() == Material.AIR)
copySpawner(event.getPlayer(), cs);
}
+ private boolean processLMSpawnEgg(final @NotNull PlayerInteractEvent event){
+ if (!VersionUtils.isRunningPaper()) return false;
+ if (event.getItem() == null) return false;
+ final ItemMeta meta = event.getItem().getItemMeta();
+ if (meta == null) return false;
+ if (event.getClickedBlock() == null) return false;
+ if (!meta.getPersistentDataContainer().has(main.namespaced_keys.spawnerEgg, PersistentDataType.INTEGER)) return false;
+
+ // we've confirmed it is a LM spawn egg. cancel the event and spawn the mob manually
+ event.setCancelled(true);
+ final Location location = event.getClickedBlock().getLocation().add(0, 1, 0);
+ int minLevel = 1;
+ int maxLevel = 1;
+ String customDropId = null;
+ EntityType spawnType = EntityType.ZOMBIE;
+
+ if (meta.getPersistentDataContainer().has(main.namespaced_keys.keySpawner_MinLevel, PersistentDataType.INTEGER)) {
+ final Integer temp = meta.getPersistentDataContainer().get(main.namespaced_keys.keySpawner_MinLevel, PersistentDataType.INTEGER);
+ if (temp != null) minLevel = temp;
+ }
+ if (meta.getPersistentDataContainer().has(main.namespaced_keys.keySpawner_MaxLevel, PersistentDataType.INTEGER)) {
+ final Integer temp = meta.getPersistentDataContainer().get(main.namespaced_keys.keySpawner_MaxLevel, PersistentDataType.INTEGER);
+ if (temp != null) maxLevel = temp;
+ }
+ if (meta.getPersistentDataContainer().has(main.namespaced_keys.keySpawner_CustomDropId, PersistentDataType.STRING))
+ customDropId = meta.getPersistentDataContainer().get(main.namespaced_keys.keySpawner_CustomDropId, PersistentDataType.STRING);
+
+ if (meta.getPersistentDataContainer().has(main.namespaced_keys.keySpawner_SpawnType, PersistentDataType.STRING)) {
+ final String temp = meta.getPersistentDataContainer().get(main.namespaced_keys.keySpawner_SpawnType, PersistentDataType.STRING);
+ if (temp != null){
+ try {
+ spawnType = EntityType.valueOf(temp);
+ } catch (final Exception ignored)
+ { Utils.logger.warning("Invalid spawn type on spawner egg: " + temp); }
+ }
+ }
+
+ String eggName = null;
+ if (meta.getPersistentDataContainer().has(main.namespaced_keys.keySpawner_CustomName, PersistentDataType.STRING))
+ eggName = meta.getPersistentDataContainer().get(main.namespaced_keys.keySpawner_CustomName, PersistentDataType.STRING);
+
+ if (Utils.isNullOrEmpty(eggName))
+ eggName = "LM Spawn Egg";
+
+ if (event.getClickedBlock().getBlockData().getMaterial() == Material.SPAWNER){
+ final SpawnerBaseClass.CustomSpawnerInfo info = new SpawnerBaseClass.CustomSpawnerInfo(main, null);
+ info.minLevel = minLevel;
+ info.maxLevel = maxLevel;
+ info.spawnType = spawnType;
+ info.customDropId = customDropId;
+ if (meta.getPersistentDataContainer().has(main.namespaced_keys.keySpawner_CustomName, PersistentDataType.STRING))
+ info.customName = meta.getPersistentDataContainer().get(main.namespaced_keys.keySpawner_CustomName, PersistentDataType.STRING);
+ if (meta.getPersistentDataContainer().has(main.namespaced_keys.keySpawner_Lore, PersistentDataType.STRING))
+ info.lore = meta.getPersistentDataContainer().get(main.namespaced_keys.keySpawner_Lore, PersistentDataType.STRING);
+
+ convertSpawner(event, info);
+ return true;
+ }
+
+ final Entity entity = location.getWorld().spawnEntity(location, spawnType, CreatureSpawnEvent.SpawnReason.SPAWNER_EGG);
+ if (!(entity instanceof LivingEntity)) return true;
+
+ final LivingEntityWrapper lmEntity = LivingEntityWrapper.getInstance((LivingEntity) entity, main);
+
+ synchronized (LevelManager.summonedOrSpawnEggs_Lock){
+ main.levelManager.summonedOrSpawnEggs.put(lmEntity.getLivingEntity(), null);
+ }
+
+ int useLevel = minLevel;
+ if (minLevel != maxLevel)
+ useLevel = ThreadLocalRandom.current().nextInt(minLevel, maxLevel + 1);
+
+ synchronized (lmEntity.getLivingEntity().getPersistentDataContainer()){
+ lmEntity.getPDC().set(main.namespaced_keys.wasSummoned, PersistentDataType.INTEGER, 1);
+ if (!Utils.isNullOrEmpty(customDropId))
+ lmEntity.getPDC().set(main.namespaced_keys.keySpawner_CustomDropId, PersistentDataType.STRING, customDropId);
+ lmEntity.getPDC().set(main.namespaced_keys.spawnerEggName, PersistentDataType.STRING, eggName);
+ }
+
+ main.levelInterface.applyLevelToMob(lmEntity, useLevel, true, true, new HashSet<>(Collections.singletonList(AdditionalLevelInformation.NOT_APPLICABLE)));
+
+ lmEntity.free();
+ return true;
+ }
+
+ private void convertSpawner(final @NotNull PlayerInteractEvent event, final SpawnerBaseClass.CustomSpawnerInfo info){
+ if (event.getClickedBlock() == null) return;
+
+ if (!event.getPlayer().hasPermission("levelledmobs.convert-spawner")){
+ showMessage("command.levelledmobs.spawner.permission-denied");
+ return;
+ }
+
+ final CreatureSpawner cs = (CreatureSpawner) event.getClickedBlock().getState();
+ final PersistentDataContainer pdc = cs.getPersistentDataContainer();
+ final boolean wasLMSpawner = pdc.has(main.namespaced_keys.keySpawner, PersistentDataType.INTEGER);
+
+ pdc.set(info.main.namespaced_keys.keySpawner, PersistentDataType.INTEGER, 1);
+ pdc.set(info.main.namespaced_keys.keySpawner_MinLevel, PersistentDataType.INTEGER, info.minLevel);
+ pdc.set(info.main.namespaced_keys.keySpawner_MaxLevel, PersistentDataType.INTEGER, info.maxLevel);
+
+ updateKeyString(main.namespaced_keys.keySpawner_CustomDropId, pdc, info.customDropId);
+ updateKeyString(info.main.namespaced_keys.keySpawner_SpawnType, pdc, info.spawnType.toString());
+ updateKeyString(info.main.namespaced_keys.keySpawner_CustomName, pdc, info.customName);
+
+ cs.setSpawnedType(info.spawnType);
+ cs.update();
+
+ if (Utils.isNullOrEmpty(info.customName))
+ info.customName = "LM Spawner";
+
+ if (!wasLMSpawner)
+ showMessage("command.levelledmobs.spawner.spawner-converted", "%spawnername%", info.customName);
+ else
+ showMessage("command.levelledmobs.spawner.spawner-updated", "%spawnername%", info.customName);
+ }
+
+ private void updateKeyString(final NamespacedKey key, final @NotNull PersistentDataContainer pdc, final @Nullable String value){
+ if (!Utils.isNullOrEmpty(value))
+ pdc.set(key, PersistentDataType.STRING, value);
+ else if (pdc.has(key, PersistentDataType.STRING))
+ pdc.remove(key);
+ }
+
private void copySpawner(final Player player, final @NotNull CreatureSpawner cs){
final SpawnerSubCommand.CustomSpawnerInfo info = new SpawnerSubCommand.CustomSpawnerInfo(main, "lm");
info.player = player;
final PersistentDataContainer pdc = cs.getPersistentDataContainer();
if (!pdc.has(main.namespaced_keys.keySpawner, PersistentDataType.INTEGER)){
- List messages = main.messagesCfg.getStringList("command.levelledmobs.spawner.copy.vanilla-spawner");
- messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%label%", "lm");
- messages = Utils.colorizeAllInList(messages);
- messages.forEach(player::sendMessage);
+ showMessage("command.levelledmobs.spawner.copy.vanilla-spawner");
return;
}
@@ -115,7 +256,7 @@ private void copySpawner(final Player player, final @NotNull CreatureSpawner cs)
info.spawnCount = cs.getSpawnCount();
info.spawnRange = cs.getSpawnRange();
- SpawnerSubCommand.generateSpawner(info);
+ main.levelledMobsCommand.spawnerSubCommand.generateSpawner(info);
}
private void showInfo(final Player player, final @NotNull CreatureSpawner cs){
@@ -144,7 +285,7 @@ private void showInfo(final Player player, final @NotNull CreatureSpawner cs){
addSpawnerAttribute("required player range", cs.getRequiredPlayerRange(), sb);
addSpawnerAttribute("spawn count", cs.getSpawnCount(), sb);
sb.append('\n');
- addSpawnerAttributeFromPdc_Str("custom drop id", main.namespaced_keys.keySpawner_CustomDropId, pdc, sb);
+ addSpawnerAttributeFromPdc_Str(main.namespaced_keys.keySpawner_CustomDropId, pdc, sb);
// customName
addSpawnerAttribute("spawn type", cs.getSpawnedType(), sb);
@@ -164,15 +305,13 @@ private void addSpawnerAttributeFromPdc_Int(final String name, final NamespacedK
sb.append("&r");
}
- private void addSpawnerAttributeFromPdc_Str(final String name, final NamespacedKey key, final @NotNull PersistentDataContainer pdc, final StringBuilder sb){
+ private void addSpawnerAttributeFromPdc_Str(final NamespacedKey key, final @NotNull PersistentDataContainer pdc, final StringBuilder sb){
if (!pdc.has(key, PersistentDataType.STRING)) return;
if (!sb.substring(sb.length() - 1).equals("\n"))
sb.append(", ");
- sb.append("&7");
- sb.append(name);
- sb.append(": &b");
+ sb.append("&7custom drop id: &b");
sb.append(pdc.get(key, PersistentDataType.STRING));
sb.append("&r");
}
diff --git a/src/main/java/me/lokka30/levelledmobs/listeners/PlayerJoinListener.java b/src/main/java/me/lokka30/levelledmobs/listeners/PlayerJoinListener.java
index d2db5ae4f..5613c411e 100644
--- a/src/main/java/me/lokka30/levelledmobs/listeners/PlayerJoinListener.java
+++ b/src/main/java/me/lokka30/levelledmobs/listeners/PlayerJoinListener.java
@@ -8,8 +8,10 @@
import me.lokka30.levelledmobs.misc.LivingEntityWrapper;
import me.lokka30.levelledmobs.misc.PlayerQueueItem;
import me.lokka30.levelledmobs.misc.Utils;
-import me.lokka30.microlib.MessageUtils;
+import me.lokka30.microlib.messaging.MessageUtils;
import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
@@ -20,6 +22,7 @@
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
+import org.bukkit.persistence.PersistentDataType;
import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.NotNull;
@@ -44,6 +47,7 @@ public PlayerJoinListener(final LevelledMobs main) {
@EventHandler(priority = EventPriority.MONITOR)
public void onJoin(@NotNull final PlayerJoinEvent event) {
main.companion.addRecentlyJoinedPlayer(event.getPlayer());
+ checkForNetherPortalCoords(event.getPlayer());
main.nametagTimerChecker.addPlayerToQueue(new PlayerQueueItem(event.getPlayer(), true));
parseCompatibilityChecker(event.getPlayer());
parseUpdateChecker(event.getPlayer());
@@ -55,6 +59,29 @@ public void onJoin(@NotNull final PlayerJoinEvent event) {
}
}
+ private void checkForNetherPortalCoords(final @NotNull Player player){
+ Location location = null;
+ try{
+ if (!player.getPersistentDataContainer().has(main.namespaced_keys.playerNetherCoords, PersistentDataType.STRING))
+ return;
+
+ final String netherCoords = player.getPersistentDataContainer().get(main.namespaced_keys.playerNetherCoords, PersistentDataType.STRING);
+ if (netherCoords == null) return;
+ final String[] coords = netherCoords.split(",");
+ if (coords.length != 4) return;
+ final World world = Bukkit.getWorld(coords[0]);
+ if (world == null) return;
+ location = new Location(world, Integer.parseInt(coords[1]), Integer.parseInt(coords[2]), Integer.parseInt(coords[3]));
+ }
+ catch (Exception e){
+ Utils.logger.warning("Unable to get player nether portal coords from " + player.getName() + ", " + e.getMessage());
+ }
+
+ if (location == null) return;
+
+ main.companion.setPlayerNetherPortalLocation(player, location);
+ }
+
@EventHandler(priority = EventPriority.MONITOR)
private void onPlayerQuitEvent(final PlayerQuitEvent event){
if (main.placeholderApiIntegration != null)
@@ -73,9 +100,13 @@ public void onChangeWorld(@NotNull final PlayerChangedWorldEvent event) {
updateNametagsInWorldAsync(event.getPlayer(), event.getPlayer().getWorld().getEntities());
}
+ @SuppressWarnings("ConstantConditions")
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onTeleport(@NotNull final PlayerTeleportEvent event) {
- if (event.getTo() != null && event.getTo().getWorld() != null)
+ // on spigot API .getTo is nullable but not Paper
+ // only update tags if teleported to a different world
+ if (event.getTo() != null && event.getTo().getWorld() != null && event.getFrom().getWorld() != null
+ && event.getFrom().getWorld() != event.getTo().getWorld())
updateNametagsInWorldAsync(event.getPlayer(), event.getTo().getWorld().getEntities());
}
@@ -113,7 +144,7 @@ private void updateNametagsInWorld(final Player player, @NotNull final List messages = main.messagesCfg.getStringList("other.compatibility-notice.messages");
messages = Utils.replaceAllInList(messages, "%prefix%", main.configUtils.getPrefix());
- messages = Utils.replaceAllInList(messages, "%incompatibilities%", main.incompatibilitiesAmount + "");
+ messages = Utils.replaceAllInList(messages, "%incompatibilities%", String.valueOf(main.incompatibilitiesAmount));
messages = Utils.colorizeAllInList(messages);
messages.forEach(player::sendMessage);
}
- void parseUpdateChecker(final Player player) {
+ private void parseUpdateChecker(final Player player) {
if (main.messagesCfg.getBoolean("other.update-notice.send-on-join", true) && player.hasPermission("levelledmobs.receive-update-notifications"))
main.companion.updateResult.forEach(player::sendMessage);
}
diff --git a/src/main/java/me/lokka30/levelledmobs/listeners/PlayerPortalEventListener.java b/src/main/java/me/lokka30/levelledmobs/listeners/PlayerPortalEventListener.java
new file mode 100644
index 000000000..d81beb468
--- /dev/null
+++ b/src/main/java/me/lokka30/levelledmobs/listeners/PlayerPortalEventListener.java
@@ -0,0 +1,57 @@
+package me.lokka30.levelledmobs.listeners;
+
+import me.lokka30.levelledmobs.LevelledMobs;
+import me.lokka30.levelledmobs.misc.Utils;
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityPortalExitEvent;
+import org.bukkit.event.player.PlayerPortalEvent;
+import org.bukkit.event.player.PlayerTeleportEvent;
+import org.bukkit.persistence.PersistentDataType;
+import org.bukkit.scheduler.BukkitRunnable;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ConcurrentModificationException;
+
+public class PlayerPortalEventListener implements Listener {
+ public PlayerPortalEventListener(final LevelledMobs main){
+ this.main = main;
+ }
+
+ private final LevelledMobs main;
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onPlayerPortalEvent(final @NotNull PlayerPortalEvent event){
+ if (event.getCause() != PlayerTeleportEvent.TeleportCause.NETHER_PORTAL) return;
+ if (event.getTo().getWorld() == null || event.getTo().getWorld().getEnvironment() != World.Environment.NETHER) return;
+
+ final Player player = event.getPlayer();
+
+ // store the player's portal coords in the nether. only used for player levelling
+ main.companion.setPlayerNetherPortalLocation(player, event.getTo());
+ final String locationStr = String.format("%s,%s,%s,%s",
+ event.getTo().getWorld().getName(), event.getTo().getBlockX(), event.getTo().getBlockY(), event.getTo().getBlockZ());
+
+ final BukkitRunnable runnable = new BukkitRunnable() {
+ @Override
+ public void run() {
+ main.companion.setPlayerNetherPortalLocation(player, player.getLocation());
+
+ try{
+ event.getPlayer().getPersistentDataContainer().set(main.namespaced_keys.playerNetherCoords, PersistentDataType.STRING, locationStr);
+ }
+ catch (ConcurrentModificationException e){
+ Utils.logger.warning("Error updating PDC on " + player.getName() + ", " + e.getMessage());
+ }
+ }
+ };
+
+ // for some reason event#getTo has different coords that the actual nether portal
+ // delay for 1 ticket and grab the player location instead
+ runnable.runTaskLater(main, 1L);
+ }
+}
diff --git a/src/main/java/me/lokka30/levelledmobs/listeners/paper/PlayerDeathListener.java b/src/main/java/me/lokka30/levelledmobs/listeners/paper/PlayerDeathListener.java
new file mode 100644
index 000000000..6c3acb630
--- /dev/null
+++ b/src/main/java/me/lokka30/levelledmobs/listeners/paper/PlayerDeathListener.java
@@ -0,0 +1,96 @@
+package me.lokka30.levelledmobs.listeners.paper;
+
+import me.lokka30.levelledmobs.LevelledMobs;
+import me.lokka30.levelledmobs.misc.LivingEntityWrapper;
+import me.lokka30.levelledmobs.misc.Utils;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.TextComponent;
+import net.kyori.adventure.text.TranslatableComponent;
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Projectile;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.entity.PlayerDeathEvent;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class PlayerDeathListener {
+ public PlayerDeathListener(final LevelledMobs main){
+ this.main = main;
+ }
+
+ private final LevelledMobs main;
+
+ public boolean onPlayerDeathEvent(final @NotNull PlayerDeathEvent event){
+ if (event.deathMessage() == null) return true;
+ if (!(event.deathMessage() instanceof TranslatableComponent)) return false;
+
+ final LivingEntityWrapper lmEntity = getPlayersKiller(event);
+
+ if (lmEntity == null){
+ if (main.placeholderApiIntegration != null)
+ main.placeholderApiIntegration.putPlayerOrMobDeath(event.getEntity(), null);
+ return true;
+ }
+
+ if (main.placeholderApiIntegration != null)
+ main.placeholderApiIntegration.putPlayerOrMobDeath(event.getEntity(), lmEntity);
+ lmEntity.free();
+
+ return true;
+ }
+
+ @Nullable
+ private LivingEntityWrapper getPlayersKiller(@NotNull final PlayerDeathEvent event){
+ final EntityDamageEvent entityDamageEvent = event.getEntity().getLastDamageCause();
+ if (entityDamageEvent == null || entityDamageEvent.isCancelled() || !(entityDamageEvent instanceof EntityDamageByEntityEvent))
+ return null;
+
+ final Entity damager = ((EntityDamageByEntityEvent) entityDamageEvent).getDamager();
+ final LivingEntity killer;
+
+ if (damager instanceof Projectile)
+ killer = (LivingEntity) ((Projectile) damager).getShooter();
+ else if (!(damager instanceof LivingEntity))
+ return null;
+ else
+ killer = (LivingEntity) damager;
+
+ if (killer == null || Utils.isNullOrEmpty(killer.getName()) || killer instanceof Player) return null;
+
+ final LivingEntityWrapper lmKiller = LivingEntityWrapper.getInstance(killer, main);
+ if (!lmKiller.isLevelled())
+ return lmKiller;
+
+ final String deathMessage = main.levelManager.getNametag(lmKiller, true);
+ if (Utils.isNullOrEmpty(deathMessage) || "disabled".equalsIgnoreCase(deathMessage))
+ return lmKiller;
+
+ updateDeathMessage(event, deathMessage);
+
+ return lmKiller;
+ }
+
+ private void updateDeathMessage(@NotNull final PlayerDeathEvent event, final String mobName){
+ final TranslatableComponent tc = (TranslatableComponent) event.deathMessage();
+ if (tc == null) return;
+ String playerKilled = null;
+
+ for (final net.kyori.adventure.text.Component com : tc.args()){
+ if (com instanceof TextComponent)
+ playerKilled = ((TextComponent) com).content();
+ }
+
+ if (playerKilled == null) return;
+
+ final TextComponent tcMobName = LegacyComponentSerializer.legacySection().deserialize(mobName);
+ final Component newCom = Component.text().content(playerKilled).build()
+ .append(Component.translatable().key(tc.key()).build())
+ .append(tcMobName);
+
+ event.deathMessage(newCom);
+ }
+}
diff --git a/src/main/java/me/lokka30/levelledmobs/managers/ExternalCompatibilityManager.java b/src/main/java/me/lokka30/levelledmobs/managers/ExternalCompatibilityManager.java
index 729bcb575..cebcb5633 100644
--- a/src/main/java/me/lokka30/levelledmobs/managers/ExternalCompatibilityManager.java
+++ b/src/main/java/me/lokka30/levelledmobs/managers/ExternalCompatibilityManager.java
@@ -6,10 +6,11 @@
import me.lokka30.levelledmobs.LevelledMobs;
import me.lokka30.levelledmobs.LivingEntityInterface;
-import me.lokka30.levelledmobs.misc.LevellableState;
-import me.lokka30.levelledmobs.misc.LivingEntityWrapper;
+import me.lokka30.levelledmobs.misc.*;
import org.bukkit.Bukkit;
+import org.bukkit.Location;
import org.bukkit.NamespacedKey;
+import org.bukkit.World;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.metadata.MetadataValue;
@@ -62,36 +63,25 @@ public enum ExternalCompatibility {
}
/* Store any external namespaced keys with null values by default */
- public static NamespacedKey dangerousCavesMobTypeKey = null;
- public static NamespacedKey ecoBossesKey = null;
+ private static NamespacedKey dangerousCavesMobTypeKey = null;
+ private static NamespacedKey ecoBossesKey = null;
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
- public static boolean isExternalCompatibilityEnabled(final ExternalCompatibility externalCompatibility, @NotNull final LivingEntityWrapper lmEntity) {
- if (lmEntity.getApplicableRules().isEmpty())
- return false;
-
- final Map list = lmEntity.getMainInstance().rulesManager.getRule_ExternalCompatibility(lmEntity);
- return isExternalCompatibilityEnabled(externalCompatibility, list);
- }
-
- public static boolean isExternalCompatibilityEnabled(final ExternalCompatibility externalCompatibility, final Map list) {
+ private static boolean isExternalCompatibilityEnabled(final ExternalCompatibility externalCompatibility, final @NotNull Map list) {
// if not defined default to true
return (!list.containsKey(externalCompatibility) || list.get(externalCompatibility) != null && list.get(externalCompatibility));
}
- public static boolean hasPAPI_Installed(){ return (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null); }
+ static boolean hasPAPI_Installed(){ return (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null); }
public static boolean hasNBTAPI_Installed(){
return Bukkit.getPluginManager().getPlugin("NBTAPI") != null;
}
- public static boolean hasMCMMO_CoreInsatlled(){
- return Bukkit.getPluginManager().getPlugin("MMOCore") != null;
- }
-
@NotNull
- public static String getPAPI_Placeholder(final Player player, final String placeholder){
+ static String getPAPI_Placeholder(final Player player, final String placeholder){
return me.clip.placeholderapi.PlaceholderAPI.setPlaceholders(player, placeholder);
+
}
public static boolean hasProtocolLibInstalled() {
@@ -102,15 +92,11 @@ public static boolean hasMythicMobsInstalled() {
return Bukkit.getPluginManager().getPlugin("MythicMobs") != null;
}
- public static boolean hasSimplePetsInstalled() {
- return Bukkit.getPluginManager().getPlugin("SimplePets") != null;
- }
-
public static boolean hasWorldGuardInstalled() {
return Bukkit.getPluginManager().getPlugin("WorldGuard") != null;
}
- public static boolean isMobOfSimplePets(@NotNull final LivingEntityWrapper lmEntity){
+ private static boolean isMobOfSimplePets(@NotNull final LivingEntityWrapper lmEntity){
final Plugin plugin = Bukkit.getPluginManager().getPlugin("SimplePets");
if (plugin == null) return false;
@@ -180,7 +166,7 @@ public static String getMythicMobInternalName(@NotNull final LivingEntityWrapper
return "";
}
- public static LevellableState checkAllExternalCompats(final LivingEntityWrapper lmEntity, final @NotNull LevelledMobs main){
+ static LevellableState checkAllExternalCompats(final LivingEntityWrapper lmEntity, final @NotNull LevelledMobs main){
final Map compatRules = main.rulesManager.getRule_ExternalCompatibility(lmEntity);
LevellableState result = LevellableState.ALLOWED;
@@ -189,31 +175,31 @@ public static LevellableState checkAllExternalCompats(final LivingEntityWrapper
result = LevellableState.DENIED_CONFIGURATION_COMPATIBILITY_DANGEROUS_CAVES;
if (isMobOfEcoBosses(lmEntity) && !isExternalCompatibilityEnabled(ExternalCompatibility.ECO_BOSSES, compatRules) &&
- result.equals(LevellableState.ALLOWED))
+ result == LevellableState.ALLOWED)
result = LevellableState.DENIED_CONFIGURATION_COMPATIBILITY_ECO_BOSSES;
if (isMobOfMythicMobs(lmEntity) && !isExternalCompatibilityEnabled(ExternalCompatibility.MYTHIC_MOBS, compatRules) &&
- result.equals(LevellableState.ALLOWED))
+ result == LevellableState.ALLOWED)
result = LevellableState.DENIED_CONFIGURATION_COMPATIBILITY_MYTHIC_MOBS;
if (isMobOfEliteMobs(lmEntity) && !isExternalCompatibilityEnabled(ExternalCompatibility.ELITE_MOBS, compatRules) &&
- result.equals(LevellableState.ALLOWED))
+ result == LevellableState.ALLOWED)
result = LevellableState.DENIED_CONFIGURATION_COMPATIBILITY_ELITE_MOBS;
if (isMobOfInfernalMobs(lmEntity) && !isExternalCompatibilityEnabled(ExternalCompatibility.INFERNAL_MOBS, compatRules) &&
- result.equals(LevellableState.ALLOWED))
+ result == LevellableState.ALLOWED)
result = LevellableState.DENIED_CONFIGURATION_COMPATIBILITY_INFERNAL_MOBS;
if (isMobOfCitizens(lmEntity) && !isExternalCompatibilityEnabled(ExternalCompatibility.CITIZENS, compatRules) &&
- result.equals(LevellableState.ALLOWED))
+ result == LevellableState.ALLOWED)
result = LevellableState.DENIED_CONFIGURATION_COMPATIBILITY_CITIZENS;
if (isMobOfShopkeepers(lmEntity) && !isExternalCompatibilityEnabled(ExternalCompatibility.SHOPKEEPERS, compatRules) &&
- result.equals(LevellableState.ALLOWED))
+ result == LevellableState.ALLOWED)
result = LevellableState.DENIED_CONFIGURATION_COMPATIBILITY_SHOPKEEPERS;
if (isMobOfSimplePets(lmEntity) && !isExternalCompatibilityEnabled(ExternalCompatibility.SIMPLE_PETS, compatRules) &&
- result.equals(LevellableState.ALLOWED))
+ result == LevellableState.ALLOWED)
result = LevellableState.DENIED_CONFIGURATION_COMPATIBILITY_SIMPLEPETS;
return result;
@@ -226,7 +212,7 @@ public static LevellableState checkAllExternalCompats(final LivingEntityWrapper
* @return if Dangerous Caves compatibility enabled and entity is from DangerousCaves
* @author lokka30, stumper66, imDaniX (author of DC2 - provided part of this method)
*/
- public static boolean isMobOfDangerousCaves(final LivingEntityWrapper lmEntity) {
+ private static boolean isMobOfDangerousCaves(final LivingEntityWrapper lmEntity) {
final Plugin plugin = Bukkit.getPluginManager().getPlugin("DangerousCaves");
if (plugin == null) return false;
@@ -247,7 +233,7 @@ public static boolean isMobOfDangerousCaves(final LivingEntityWrapper lmEntity)
* @return if the compat is enabled and if the mob belongs to EcoBosses
* @author lokka30, Auxilor (author of EcoBosses - provided part of this method)
*/
- public static boolean isMobOfEcoBosses(final LivingEntityWrapper lmEntity) {
+ private static boolean isMobOfEcoBosses(final LivingEntityWrapper lmEntity) {
final Plugin plugin = Bukkit.getPluginManager().getPlugin("EcoBosses");
if (plugin == null) return false;
@@ -267,7 +253,7 @@ public static boolean isMobOfEcoBosses(final LivingEntityWrapper lmEntity) {
* @param lmEntity mob to check
* @return if MythicMobs compatibility enabled and entity is from MythicMobs
*/
- public static boolean isMobOfMythicMobs(final LivingEntityWrapper lmEntity) {
+ private static boolean isMobOfMythicMobs(final LivingEntityWrapper lmEntity) {
if (!ExternalCompatibilityManager.hasMythicMobsInstalled()) return false;
if (lmEntity.isMobOfExternalType(ExternalCompatibility.MYTHIC_MOBS)) return true;
@@ -281,10 +267,10 @@ public static boolean isMobOfMythicMobs(final LivingEntityWrapper lmEntity) {
* @param lmEntity mob to check
* @return if EliteMobs compatibility enabled and entity is from EliteMobs
*/
- public static boolean isMobOfEliteMobs(final @NotNull LivingEntityWrapper lmEntity) {
+ private static boolean isMobOfEliteMobs(final LivingEntityWrapper lmEntity) {
final Plugin p = Bukkit.getPluginManager().getPlugin("EliteMobs");
if (p != null){
- boolean isEliteMob;
+ final boolean isEliteMob;
synchronized (lmEntity.getLivingEntity().getPersistentDataContainer()) {
isEliteMob = lmEntity.getPDC().has(new NamespacedKey(p, "EliteMobsCullable"), PersistentDataType.STRING);
}
@@ -302,7 +288,7 @@ public static boolean isMobOfEliteMobs(final @NotNull LivingEntityWrapper lmEnti
* @param lmEntity mob to check
* @return if InfernalMobs compatibility enabled and entity is from InfernalMobs
*/
- public static boolean isMobOfInfernalMobs(final @NotNull LivingEntityWrapper lmEntity) {
+ private static boolean isMobOfInfernalMobs(final @NotNull LivingEntityWrapper lmEntity) {
final boolean isExternalType = lmEntity.getLivingEntity().hasMetadata("infernalMetadata");
if (isExternalType) lmEntity.setMobExternalType(ExternalCompatibility.INFERNAL_MOBS);
@@ -314,7 +300,7 @@ public static boolean isMobOfInfernalMobs(final @NotNull LivingEntityWrapper lmE
* @param lmEntity mob to check
* @return if Citizens compatibility enabled and entity is from Citizens
*/
- public static boolean isMobOfCitizens(final @NotNull LivingEntityWrapper lmEntity) {
+ private static boolean isMobOfCitizens(final @NotNull LivingEntityWrapper lmEntity) {
final boolean isExternalType = isMobOfCitizens(lmEntity.getLivingEntity());
if (isExternalType) lmEntity.setMobExternalType(ExternalCompatibility.CITIZENS);
@@ -330,7 +316,7 @@ public static boolean isMobOfCitizens(final @NotNull LivingEntity livingEntity)
* @param lmEntity mob to check
* @return if Shopkeepers compatibility enabled and entity is from Shopkeepers
*/
- public static boolean isMobOfShopkeepers(final @NotNull LivingEntityWrapper lmEntity) {
+ private static boolean isMobOfShopkeepers(final @NotNull LivingEntityWrapper lmEntity) {
final boolean isExternalType = lmEntity.getLivingEntity().hasMetadata("shopkeeper");
if (isExternalType) lmEntity.setMobExternalType(ExternalCompatibility.SHOPKEEPERS);
@@ -344,4 +330,30 @@ public static List getWGRegionsAtLocation(@NotNull final LivingEntityInt
return WorldGuardIntegration.getWorldGuardRegionsForLocation(lmInterface);
}
+
+ @NotNull
+ public static PlayerHomeCheckResult getPlayerHomeLocation(final @NotNull LevelledMobs main, final @NotNull Player player, final boolean allowBed){
+ final Plugin plugin = Bukkit.getPluginManager().getPlugin("essentials");
+ if (plugin == null)
+ return new PlayerHomeCheckResult("Unable to get player home, Essentials is not installed", null);
+
+ if (allowBed && player.getWorld().getEnvironment() != World.Environment.NETHER) {
+ final Location bedLocation = player.getBedSpawnLocation();
+ if (bedLocation != null)
+ return new PlayerHomeCheckResult(null, bedLocation, "bed");
+ }
+
+ final com.earth2me.essentials.Essentials essentials = (com.earth2me.essentials.Essentials) plugin;
+ final com.earth2me.essentials.User user = essentials.getUser(player);
+ if (user == null)
+ return new PlayerHomeCheckResult("Unable to locate player information in essentials");
+
+ if (user.getHomes() == null || user.getHomes().isEmpty()) {
+ PlayerNetherOrWorldSpawnResult result = Utils.getNetherPortalOrWorldSpawn(main, player);
+ final String whichSource = result.isNetherPortalLocation ? "nether portal" : "spawn";
+ return new PlayerHomeCheckResult("Player has no homes set, using " + whichSource + " location", result.location);
+ }
+
+ return new PlayerHomeCheckResult(null, user.getHome(user.getHomes().get(0)), user.getHomes().get(0));
+ }
}
diff --git a/src/main/java/me/lokka30/levelledmobs/managers/LevelManager.java b/src/main/java/me/lokka30/levelledmobs/managers/LevelManager.java
index 91a01df2f..cfb8550ed 100644
--- a/src/main/java/me/lokka30/levelledmobs/managers/LevelManager.java
+++ b/src/main/java/me/lokka30/levelledmobs/managers/LevelManager.java
@@ -18,7 +18,7 @@
import me.lokka30.levelledmobs.rules.strategies.RandomLevellingStrategy;
import me.lokka30.levelledmobs.rules.strategies.SpawnDistanceStrategy;
import me.lokka30.levelledmobs.rules.strategies.YDistanceStrategy;
-import me.lokka30.microlib.MessageUtils;
+import me.lokka30.microlib.messaging.MessageUtils;
import org.bukkit.*;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
@@ -48,18 +48,29 @@
*/
public class LevelManager implements LevelInterface {
+ public LevelManager(final LevelledMobs main) {
+ this.main = main;
+ this.randomLevellingCache = new TreeMap<>();
+ this.summonedOrSpawnEggs = new WeakHashMap<>();
+
+ this.vehicleNoMultiplierItems = Arrays.asList(
+ Material.SADDLE,
+ Material.LEATHER_HORSE_ARMOR,
+ Material.IRON_HORSE_ARMOR,
+ Material.GOLDEN_HORSE_ARMOR,
+ Material.DIAMOND_HORSE_ARMOR
+ );
+ }
+
private final LevelledMobs main;
- private final static int maxLevelNumsCache = 10;
- final private List vehicleNoMultiplierItems;
+ private final List vehicleNoMultiplierItems;
public double attributeMaxHealthMax = 2048.0;
public double attributeMovementSpeedMax = 2048.0;
public double attributeAttackDamageMax = 2048.0;
- public Location summonedLocation;
- public EntityType summonedEntityType;
+ public final Map summonedOrSpawnEggs;
+ public static final Object summonedOrSpawnEggs_Lock = new Object();
private boolean hasMentionedNBTAPI_Missing;
private final Map randomLevellingCache;
-
- public final static int maxCreeperBlastRadius = 100;
public EntitySpawnListener entitySpawnListener;
/**
@@ -77,27 +88,6 @@ public class LevelManager implements LevelInterface {
"TRIDENT", "UNKNOWN", "WITHER_SKULL"
));
- /**
- * The following entity types must be manually ALLOWED in 'getLevellableState',
- * as they are not instanceof Monster or Boss
- * Stored as Strings since older versions may not contain certain entity type constants
- */
- public final HashSet OTHER_HOSTILE_MOBS = new HashSet<>(Arrays.asList("GHAST", "HOGLIN", "SHULKER", "PHANTOM", "ENDER_DRAGON", "SLIME", "MAGMA_CUBE", "ZOMBIFIED_PIGLIN"));
-
- public LevelManager(final LevelledMobs main) {
- this.main = main;
- this.summonedEntityType = EntityType.UNKNOWN;
- this.randomLevellingCache = new TreeMap<>();
-
- this.vehicleNoMultiplierItems = Arrays.asList(
- Material.SADDLE,
- Material.LEATHER_HORSE_ARMOR,
- Material.IRON_HORSE_ARMOR,
- Material.GOLDEN_HORSE_ARMOR,
- Material.DIAMOND_HORSE_ARMOR
- );
- }
-
public void clearRandomLevellingCache(){
this.randomLevellingCache.clear();
}
@@ -111,7 +101,7 @@ public void clearRandomLevellingCache(){
* @param lmEntity the entity to generate a level for
* @return a level for the entity
*/
- public int generateLevel(final LivingEntityWrapper lmEntity) {
+ public int generateLevel(final @NotNull LivingEntityWrapper lmEntity) {
return generateLevel(lmEntity, -1, -1);
}
@@ -126,7 +116,7 @@ public int generateLevel(final LivingEntityWrapper lmEntity) {
* @param maxLevel_Pre the maximum level to be used for the mob
* @return a level for the entity
*/
- public int generateLevel(final LivingEntityWrapper lmEntity, final int minLevel_Pre, final int maxLevel_Pre) {
+ public int generateLevel(final @NotNull LivingEntityWrapper lmEntity, final int minLevel_Pre, final int maxLevel_Pre) {
int minLevel = minLevel_Pre;
int maxLevel = maxLevel_Pre;
@@ -176,7 +166,7 @@ private int generateRandomLevel(RandomLevellingStrategy randomLevelling, final i
return randomLevelling.generateLevel(minLevel, maxLevel);
}
- private int[] getPlayerLevels(final @NotNull LivingEntityWrapper lmEntity){
+ private int @Nullable [] getPlayerLevels(final @NotNull LivingEntityWrapper lmEntity){
final PlayerLevellingOptions options = main.rulesManager.getRule_PlayerLevellingOptions(lmEntity);
if (options == null) return null;
@@ -188,26 +178,35 @@ private int[] getPlayerLevels(final @NotNull LivingEntityWrapper lmEntity){
final double scale = options.playerLevelScale != null ? options.playerLevelScale : 1.0;
final boolean usePlayerMax = options.usePlayerMaxLevel != null && options.matchPlayerLevel;
final boolean matchPlayerLvl = options.matchPlayerLevel != null && options.matchPlayerLevel;
- final double origLevelSource = getPlayerLevelSourceNumber(lmEntity.getPlayerForLevelling(), variableToUse);
+ final PlayerLevelSourceResult playerLevelSourceResult = getPlayerLevelSourceNumber(lmEntity.getPlayerForLevelling(), variableToUse);
+ final double origLevelSource = playerLevelSourceResult.isNumericResult ? playerLevelSourceResult.numericResult : 1;
levelSource = (int) Math.round(origLevelSource * scale);
if (levelSource < 1) levelSource = 1;
- final int[] results = new int[]{ 1, 1};
+ final int[] results = { 1, 1};
String tierMatched = null;
final String capDisplay = options.levelCap == null ? "" : "cap: " + options.levelCap + ", ";
if (usePlayerMax) {
results[0] = levelSource;
results[1] = results[0];
- } else if (matchPlayerLvl) {
+ } else if (matchPlayerLvl)
results[1] = levelSource;
- } else {
+ else {
boolean foundMatch = false;
for (final LevelTierMatching tier : options.levelTiers) {
- final boolean meetsMin = (tier.minLevel == null || levelSource >= tier.minLevel);
- final boolean meetsMax = (tier.maxLevel == null || levelSource <= tier.maxLevel);
+ boolean meetsMin = false;
+ boolean meetsMax = false;
+ boolean hasStringMatch = false;
+
+ if (!playerLevelSourceResult.isNumericResult && tier.sourceTierName != null)
+ hasStringMatch = playerLevelSourceResult.stringResult.equalsIgnoreCase(tier.sourceTierName);
+ else if (playerLevelSourceResult.isNumericResult) {
+ meetsMin = (tier.minLevel == null || levelSource >= tier.minLevel);
+ meetsMax = (tier.maxLevel == null || levelSource <= tier.maxLevel);
+ }
- if (meetsMin && meetsMax) {
+ if (meetsMin && meetsMax || hasStringMatch) {
if (tier.valueRanges[0] > 0) results[0] = tier.valueRanges[0];
if (tier.valueRanges[1] > 0) results[1] = tier.valueRanges[1];
tierMatched = tier.toString();
@@ -217,9 +216,16 @@ private int[] getPlayerLevels(final @NotNull LivingEntityWrapper lmEntity){
}
if (!foundMatch) {
- Utils.debugLog(main, DebugType.PLAYER_LEVELLING, String.format(
- "mob: %s, player: %s, lvl-src: %s, lvl-scale: %s, %sno tiers matched",
- lmEntity.getNameIfBaby(), player.getName(), origLevelSource, levelSource, capDisplay));
+ if (playerLevelSourceResult.isNumericResult) {
+ Utils.debugLog(main, DebugType.PLAYER_LEVELLING, String.format(
+ "mob: %s, player: %s, lvl-src: %s, lvl-scale: %s, %sno tiers matched",
+ lmEntity.getNameIfBaby(), player.getName(), origLevelSource, levelSource, capDisplay));
+ }
+ else {
+ Utils.debugLog(main, DebugType.PLAYER_LEVELLING, String.format(
+ "mob: %s, player: %s, lvl-src: '%s', %sno tiers matched",
+ lmEntity.getNameIfBaby(), player.getName(), playerLevelSourceResult.stringResult, capDisplay));
+ }
return null;
}
}
@@ -231,34 +237,101 @@ private int[] getPlayerLevels(final @NotNull LivingEntityWrapper lmEntity){
results[1] = options.levelCap;
}
+ final String homeName = playerLevelSourceResult.homeNameUsed != null ?
+ String.format(" (%s)", playerLevelSourceResult.homeNameUsed) : "";
+
if (tierMatched == null) {
Utils.debugLog(main, DebugType.PLAYER_LEVELLING, String.format(
- "mob: %s, player: %s, lvl-src: %s, lvl-scale: %s, %sresult: %s",
- lmEntity.getNameIfBaby(), player.getName(), origLevelSource, levelSource, capDisplay, Arrays.toString(results)));
+ "mob: %s, player: %s, lvl-src: %s%s, lvl-scale: %s, %sresult: %s",
+ lmEntity.getNameIfBaby(), player.getName(), origLevelSource, homeName, levelSource, capDisplay, Arrays.toString(results)));
} else {
- Utils.debugLog(main, DebugType.PLAYER_LEVELLING, String.format(
- "mob: %s, player: %s, lvl-src: %s, lvl-scale: %s, tier: %s, %sresult: %s",
- lmEntity.getNameIfBaby(), player.getName(), origLevelSource, levelSource, tierMatched, capDisplay, Arrays.toString(results)));
+ if (playerLevelSourceResult.isNumericResult) {
+ Utils.debugLog(main, DebugType.PLAYER_LEVELLING, String.format(
+ "mob: %s, player: %s, lvl-src: %s%s, lvl-scale: %s, tier: %s, %sresult: %s",
+ lmEntity.getNameIfBaby(), player.getName(), origLevelSource, homeName, levelSource, tierMatched, capDisplay, Arrays.toString(results)));
+ }
+ else {
+ Utils.debugLog(main, DebugType.PLAYER_LEVELLING, String.format(
+ "mob: %s, player: %s, lvl-src: '%s', tier: %s, %sresult: %s",
+ lmEntity.getNameIfBaby(), player.getName(), playerLevelSourceResult.stringResult, tierMatched, capDisplay, Arrays.toString(results)));
+ }
}
+ lmEntity.playerLevellingAllowDecrease = options.decreaseLevel;
+
return results;
}
- public int getPlayerLevelSourceNumber(final Player player, final String variableToUse){
- if (player == null) return 1;
+ public PlayerLevelSourceResult getPlayerLevelSourceNumber(final Player player, final String variableToUse){
+ if (player == null) return new PlayerLevelSourceResult(1);
- double origLevelSource;
+ final double origLevelSource;
+ final PlayerLevelSourceResult sourceResult = new PlayerLevelSourceResult(1);
- if (variableToUse.equalsIgnoreCase("%level%"))
+ if ("%level%".equalsIgnoreCase(variableToUse))
origLevelSource = player.getLevel();
- else if (variableToUse.equalsIgnoreCase("%exp%"))
+ else if ("%exp%".equalsIgnoreCase(variableToUse))
origLevelSource = player.getExp();
- else if (variableToUse.equalsIgnoreCase("%exp-to-level%"))
+ else if ("%exp-to-level%".equalsIgnoreCase(variableToUse))
origLevelSource = player.getExpToLevel();
- else if (variableToUse.equalsIgnoreCase("%total-exp%"))
+ else if ("%total-exp%".equalsIgnoreCase(variableToUse))
origLevelSource = player.getTotalExperience();
- else if (variableToUse.equalsIgnoreCase("%world_time_ticks%"))
+ else if ("%world_time_ticks%".equalsIgnoreCase(variableToUse))
origLevelSource = player.getWorld().getTime();
+ else if ("%home_distance%".equalsIgnoreCase(variableToUse) || "%home_distance_with_bed%".equalsIgnoreCase(variableToUse)){
+ final boolean allowBed = "%home_distance_with_bed%".equalsIgnoreCase(variableToUse);
+ boolean noHomesFound = false;
+ PlayerNetherOrWorldSpawnResult netherOrWorldSpawnResult = null;
+ final PlayerHomeCheckResult result = ExternalCompatibilityManager.getPlayerHomeLocation(main, player, allowBed);
+ sourceResult.homeNameUsed = result.homeNameUsed;
+
+ Location useLocation = result.location;
+ if (useLocation == null && player.getWorld().getEnvironment() == World.Environment.NETHER){
+ netherOrWorldSpawnResult = Utils.getNetherPortalOrWorldSpawn(main, player);
+ useLocation = netherOrWorldSpawnResult.location;
+ }
+
+ if (useLocation == null) {
+ if (result.resultMessage != null)
+ Utils.debugLog(main, DebugType.PLAYER_LEVELLING, result.resultMessage);
+ }
+ else if (useLocation.getWorld() != player.getWorld()){
+ useLocation = null;
+ noHomesFound = true;
+ }
+ else if (result.resultMessage != null)
+ Utils.debugLog(main, DebugType.PLAYER_LEVELLING, result.resultMessage);
+
+ if (useLocation == null) {
+ netherOrWorldSpawnResult = Utils.getNetherPortalOrWorldSpawn(main, player);
+ useLocation = netherOrWorldSpawnResult.location;
+ }
+
+ if (noHomesFound) {
+ final String whichSource = netherOrWorldSpawnResult.isNetherPortalLocation ? "nether portal" : "spawn";
+ Utils.debugLog(main, DebugType.PLAYER_LEVELLING, "player is in a different world from home, using " + whichSource + " distance");
+ }
+ origLevelSource = useLocation.distance(player.getLocation());
+ }
+ else if ("%bed_distance%".equalsIgnoreCase(variableToUse)){
+ Location useLocation = player.getBedSpawnLocation();
+ sourceResult.homeNameUsed = "bed";
+
+ if (player.getWorld().getEnvironment() == World.Environment.NETHER){
+ final PlayerNetherOrWorldSpawnResult result = Utils.getNetherPortalOrWorldSpawn(main, player);
+ useLocation = result.location;
+ sourceResult.homeNameUsed = "nether_portal";
+ }
+
+ if (useLocation != null && useLocation.getWorld() == player.getWorld()) {
+ origLevelSource = useLocation.distance(player.getLocation());
+ }
+ else{
+ Utils.debugLog(main, DebugType.PLAYER_LEVELLING, "no bed set for player, using spawn distance");
+ origLevelSource = player.getWorld().getSpawnLocation().distance(player.getLocation());
+ sourceResult.homeNameUsed = "spawn";
+ }
+ }
else{
boolean usePlayerLevel = false;
String PAPIResult = null;
@@ -275,7 +348,6 @@ else if (!Utils.isDouble(PAPIResult)) {
final Location l = player.getLocation();
Utils.debugLog(main, DebugType.PLAYER_LEVELLING, String.format("Got invalid number for '%s', result: '%s' from PAPI. Player %s at %s,%s,%s in %s",
variableToUse, PAPIResult, player.getName(), l.getBlockX(), l.getBlockY(), l.getBlockZ(), player.getWorld().getName()));
- usePlayerLevel = true;
}
} else {
Utils.logger.warning("PlaceHolderAPI is not installed, unable to get variable " + variableToUse);
@@ -285,10 +357,11 @@ else if (!Utils.isDouble(PAPIResult)) {
if (usePlayerLevel)
origLevelSource = player.getLevel();
else
- origLevelSource = (int) Double.parseDouble(PAPIResult);
+ origLevelSource = Double.parseDouble(PAPIResult);
}
- return (int) Math.round(origLevelSource);
+ sourceResult.numericResult = (int) Math.round(origLevelSource);
+ return sourceResult;
}
public int[] getMinAndMaxLevels(final @NotNull LivingEntityInterface lmInterface) {
@@ -356,7 +429,7 @@ public void setLevelledItemDrops(final LivingEntityWrapper lmEntity, final List<
if (!dropsToMultiply.isEmpty()) currentDrops.addAll(dropsToMultiply);
}
- public void multiplyDrop(LivingEntityWrapper lmEntity, @NotNull final ItemStack currentDrop, final int addition, final boolean isCustomDrop){
+ public void multiplyDrop(final LivingEntityWrapper lmEntity, @NotNull final ItemStack currentDrop, final int addition, final boolean isCustomDrop){
Utils.debugLog(main, DebugType.SET_LEVELLED_ITEM_DROPS, "&86:&7 Scanning drop &b" + currentDrop.getType() + "&7 with current amount &b" + currentDrop.getAmount() + "&7...");
if (isCustomDrop || main.mobDataManager.isLevelledDropManaged(lmEntity.getLivingEntity().getType(), currentDrop.getType())) {
@@ -382,7 +455,7 @@ private List getDropsToMultiply(@NotNull final LivingEntityWrapper lm
final ItemStack[] chestItems = inv.getContents();
// look thru the animal's inventory for leather. That is the only item that will get duplicated
for (final ItemStack item : chestItems){
- if (item.getType().equals(Material.LEATHER))
+ if (item.getType() == Material.LEATHER)
return Collections.singletonList(item);
}
@@ -414,7 +487,7 @@ public void removeVanillaDrops(@NotNull final LivingEntityWrapper lmEntity, fina
chestItems.add(new ItemStack(Material.CHEST));
} else if (lmEntity.getLivingEntity() instanceof Vehicle) {
for (final ItemStack itemStack : drops) {
- if (itemStack.getType().equals(Material.SADDLE)) {
+ if (itemStack.getType() == Material.SADDLE) {
hadSaddle = true;
break;
}
@@ -458,7 +531,7 @@ public String getNametag(final LivingEntityWrapper lmEntity, final boolean isDea
@NotNull
public String updateNametag(final LivingEntityWrapper lmEntity, @NotNull String nametag, final boolean useCustomNameForNametags) {
- if ("".equals(nametag)) return nametag;
+ if (nametag.isEmpty()) return nametag;
final String overridenName = main.rulesManager.getRule_EntityOverriddenName(lmEntity, useCustomNameForNametags);
String displayName = overridenName == null ?
@@ -468,7 +541,7 @@ public String updateNametag(final LivingEntityWrapper lmEntity, @NotNull String
if (lmEntity.getLivingEntity().getCustomName() != null && !useCustomNameForNametags)
displayName = lmEntity.getLivingEntity().getCustomName();
- nametag = replaceStringPlaceholders(nametag, lmEntity, displayName);
+ nametag = replaceStringPlaceholders(nametag, lmEntity);
// This is after colorize so that color codes in nametags dont get translated
nametag = nametag.replace("%displayname%", displayName);
@@ -489,11 +562,9 @@ private String formatHealthIndicator(final LivingEntityWrapper lmEntity){
if (indicator == null || mobHealth == 0.0) return "";
- final StringBuilder sb = new StringBuilder();
final int maxIndicators = indicator.maxIndicators != null ? indicator.maxIndicators : 10;
final String indicatorStr = indicator.indicator != null ? indicator.indicator : "▐";
final double scale = indicator.scale != null ? indicator.scale : 5.0;
- final double healthPerTier = scale * maxIndicators;
int indicatorsToUse = scale == 0 ?
(int) Math.ceil(mobHealth) : (int) Math.ceil(mobHealth / scale);
@@ -540,15 +611,15 @@ else if (indicator.tiers.containsKey(0))
return MessageUtils.colorizeAll(result);
}
- public String replaceStringPlaceholders(final String nametag, @NotNull final LivingEntityWrapper lmEntity, final String displayName){
+ public String replaceStringPlaceholders(final String nametag, @NotNull final LivingEntityWrapper lmEntity){
String result = nametag;
- final double maxHealth = getMobAttributeValue(lmEntity, Attribute.GENERIC_MAX_HEALTH);
+ final double maxHealth = getMobAttributeValue(lmEntity);
final double entityHealth = getMobHealth(lmEntity);
final int entityHealthRounded = entityHealth < 1.0 && entityHealth > 0.0 ?
1 : (int) Utils.round(entityHealth);
- final String roundedMaxHealth = Utils.round(maxHealth) + "";
- final String roundedMaxHealthInt = (int) Utils.round(maxHealth) + "";
+ final String roundedMaxHealth = String.valueOf(Utils.round(maxHealth));
+ final String roundedMaxHealthInt = String.valueOf((int) Utils.round(maxHealth));
final double percentHealthTemp = Math.round(entityHealth / maxHealth * 100.0);
final int percentHealth = percentHealthTemp < 1.0 ? 1 : (int) percentHealthTemp;
@@ -561,10 +632,10 @@ public String replaceStringPlaceholders(final String nametag, @NotNull final Liv
lmEntity.getLivingEntity().getLocation().getBlockZ());
// replace them placeholders ;)
- result = result.replace("%mob-lvl%", lmEntity.getMobLevel() + "");
+ result = result.replace("%mob-lvl%", String.valueOf(lmEntity.getMobLevel()));
result = result.replace("%entity-name%", Utils.capitalize(lmEntity.getNameIfBaby().replace("_", " ")));
- result = result.replace("%entity-health%", Utils.round(entityHealth) + "");
- result = result.replace("%entity-health-rounded%", entityHealthRounded + "");
+ result = result.replace("%entity-health%", String.valueOf(Utils.round(entityHealth)));
+ result = result.replace("%entity-health-rounded%", String.valueOf(entityHealthRounded));
result = result.replace("%entity-max-health%", roundedMaxHealth);
result = result.replace("%entity-max-health-rounded%", roundedMaxHealthInt);
result = result.replace("%heart_symbol%", "❤");
@@ -572,10 +643,10 @@ public String replaceStringPlaceholders(final String nametag, @NotNull final Liv
result = result.replace("%wg_region%", lmEntity.getWGRegionName());
result = result.replace("%world%", lmEntity.getWorldName());
result = result.replace("%location%", locationStr);
- result = result.replace("%health%-percent%", percentHealth + "");
- result = result.replace("%x%", lmEntity.getLivingEntity().getLocation().getBlockX() + "");
- result = result.replace("%y%", lmEntity.getLivingEntity().getLocation().getBlockY() + "");
- result = result.replace("%z%", lmEntity.getLivingEntity().getLocation().getBlockZ() + "");
+ result = result.replace("%health%-percent%", String.valueOf(percentHealth));
+ result = result.replace("%x%", String.valueOf(lmEntity.getLivingEntity().getLocation().getBlockX()));
+ result = result.replace("%y%", String.valueOf(lmEntity.getLivingEntity().getLocation().getBlockY()));
+ result = result.replace("%z%", String.valueOf(lmEntity.getLivingEntity().getLocation().getBlockZ()));
if (result.contains("%") && ExternalCompatibilityManager.hasPAPI_Installed())
result = ExternalCompatibilityManager.getPAPI_Placeholder(null, result);
@@ -609,7 +680,7 @@ public void updateNametag(final LivingEntityWrapper lmEntity){
main.nametagQueueManager_.addToQueue(queueItem);
}
- public void updateNametag(final @NotNull LivingEntityWrapper lmEntity, final String nametag) {
+ private void updateNametag(final @NotNull LivingEntityWrapper lmEntity, final String nametag) {
updateNametag(lmEntity, nametag, lmEntity.getLivingEntity().getWorld().getPlayers());
}
@@ -628,7 +699,7 @@ public void updateNametag(final @NotNull LivingEntityWrapper lmEntity, final Str
*/
public BukkitTask nametagAutoUpdateTask;
- public BukkitTask nametagTimerTask;
+ private BukkitTask nametagTimerTask;
public void startNametagAutoUpdateTask() {
Utils.logger.info("&fTasks: &7Starting async nametag auto update task...");
@@ -699,7 +770,6 @@ private void runNametagCheck_aSync(final @NotNull Map> entit
wrapperHasReference = true;
}
- boolean useResetTimer = false;
if (lmEntity.getLivingEntity() == null) continue;
final List nametagVisibilityEnums = main.rulesManager.getRule_CreatureNametagVisbility(lmEntity);
final int nametagVisibleTime = lmEntity.getNametagCooldownTime();
@@ -714,7 +784,7 @@ private void runNametagCheck_aSync(final @NotNull Map> entit
checkLevelledEntity(lmEntity, player);
} else {
- boolean wasBabyMob;
+ final boolean wasBabyMob;
synchronized (lmEntity.getLivingEntity().getPersistentDataContainer()) {
wasBabyMob = lmEntity.getPDC().has(main.namespaced_keys.wasBabyMobKey, PersistentDataType.INTEGER);
}
@@ -727,8 +797,10 @@ private void runNametagCheck_aSync(final @NotNull Map> entit
Utils.debugLog(main, DebugType.ENTITY_MISC, "&b" + lmEntity.getTypeName() + " &7was a baby and is now an adult, applying levelling rules");
main._mobsQueueManager.addToQueue(new QueueItem(lmEntity, null));
- } else if (levellableState == LevellableState.ALLOWED)
+ } else if (levellableState == LevellableState.ALLOWED) {
+ Utils.logger.info("async, levelling mob 2");
main._mobsQueueManager.addToQueue(new QueueItem(lmEntity, null));
+ }
}
}
@@ -737,9 +809,10 @@ private void runNametagCheck_aSync(final @NotNull Map> entit
}
}
- for (final LivingEntityWrapper lmEntity : entityToPlayer.keySet()) {
+ for (final Map.Entry> entry : entityToPlayer.entrySet()) {
+ final LivingEntityWrapper lmEntity = entry.getKey();
if (entityToPlayer.containsKey(lmEntity))
- checkEntityForPlayerLevelling(lmEntity, entityToPlayer.get(lmEntity));
+ checkEntityForPlayerLevelling(lmEntity, entry.getValue());
lmEntity.free();
}
@@ -749,7 +822,7 @@ private void checkEntityForPlayerLevelling(final @NotNull LivingEntityWrapper lm
final LivingEntity mob = lmEntity.getLivingEntity();
final List sortedPlayers = players.stream()
.filter(p -> mob.getWorld().equals(p.getWorld()))
- .filter(p -> !p.getGameMode().equals(GameMode.SPECTATOR))
+ .filter(p -> p.getGameMode() != GameMode.SPECTATOR)
.map(p -> Map.entry(mob.getLocation().distanceSquared(p.getLocation()), p))
.sorted(Comparator.comparingDouble(Map.Entry::getKey))
.map(Map.Entry::getValue)
@@ -775,11 +848,7 @@ private void checkEntityForPlayerLevelling(final @NotNull LivingEntityWrapper lm
}
if (doesMobNeedRelevelling(mob, closestPlayer)) {
-
- synchronized (mob.getPersistentDataContainer()) {
- mob.getPersistentDataContainer().set(main.namespaced_keys.playerLevelling_Id, PersistentDataType.STRING, closestPlayer.getUniqueId().toString());
- }
-
+ lmEntity.pendingPlayerIdToSet = closestPlayer.getUniqueId().toString();
lmEntity.setPlayerForLevelling(closestPlayer);
lmEntity.reEvaluateLevel = true;
main._mobsQueueManager.addToQueue(new QueueItem(lmEntity, null));
@@ -815,7 +884,7 @@ private boolean doesMobNeedRelevelling(final @NotNull LivingEntity mob, final @N
if (duration.toMillis() < main.playerLevellingMinRelevelTime) return false;
}
- String playerId;
+ final String playerId;
if (main.playerLevellingMinRelevelTime > 0)
main.playerLevellingEntities.put(mob, Instant.now());
@@ -846,11 +915,11 @@ public void stopNametagAutoUpdateTask() {
}
}
- public void applyLevelledAttributes(@NotNull final LivingEntityWrapper lmEntity, @NotNull final Addition addition) {
+ private void applyLevelledAttributes(@NotNull final LivingEntityWrapper lmEntity, @NotNull final Addition addition) {
assert lmEntity.isLevelled();
// This functionality should be added into the enum.
- Attribute attribute;
+ final Attribute attribute;
switch (addition) {
case ATTRIBUTE_MAX_HEALTH: attribute = Attribute.GENERIC_MAX_HEALTH; break;
case ATTRIBUTE_ATTACK_DAMAGE: attribute = Attribute.GENERIC_ATTACK_DAMAGE; break;
@@ -878,7 +947,7 @@ public void applyLevelledAttributes(@NotNull final LivingEntityWrapper lmEntity,
main.mobDataManager.setAdditionsForLevel(lmEntity, attribute, addition);
}
- public void applyCreeperBlastRadius(final @NotNull LivingEntityWrapper lmEntity, int level) {
+ private void applyCreeperBlastRadius(final @NotNull LivingEntityWrapper lmEntity) {
final Creeper creeper = (Creeper) lmEntity.getLivingEntity();
final FineTuningAttributes tuning = main.rulesManager.getFineTuningAttributes(lmEntity);
@@ -892,7 +961,7 @@ public void applyCreeperBlastRadius(final @NotNull LivingEntityWrapper lmEntity,
}
final int maxRadius = main.rulesManager.getRule_CreeperMaxBlastRadius(lmEntity);
- double damage = main.mobDataManager.getAdditionsForLevel(lmEntity, Addition.CREEPER_BLAST_DAMAGE, 3);
+ final double damage = main.mobDataManager.getAdditionsForLevel(lmEntity, Addition.CREEPER_BLAST_DAMAGE, 3);
int blastRadius = 3 + (int) Math.floor(damage);
if (blastRadius > maxRadius) blastRadius = maxRadius;
@@ -915,7 +984,7 @@ public void applyCreeperBlastRadius(final @NotNull LivingEntityWrapper lmEntity,
* @param lmEntity a levelled mob to apply levelled equipment to
* @param level the level of the levelled mob
*/
- public void applyLevelledEquipment(@NotNull final LivingEntityWrapper lmEntity, final int level) {
+ private void applyLevelledEquipment(@NotNull final LivingEntityWrapper lmEntity, final int level) {
if (!lmEntity.isLevelled()) {
// if you summon a mob and it isn't levelled due to a config rule (baby zombies exempt for example)
// then we'll be here with a non-levelled entity
@@ -965,10 +1034,10 @@ public void applyLevelledEquipment(@NotNull final LivingEntityWrapper lmEntity,
}
}
- public double getMobAttributeValue(@NotNull final LivingEntityWrapper lmEntity, final Attribute attribute){
+ private double getMobAttributeValue(@NotNull final LivingEntityWrapper lmEntity){
double result = 0.0;
synchronized (main.attributeSyncObject){
- final AttributeInstance attrib = lmEntity.getLivingEntity().getAttribute(attribute);
+ final AttributeInstance attrib = lmEntity.getLivingEntity().getAttribute(Attribute.GENERIC_MAX_HEALTH);
if (attrib != null)
result = attrib.getValue();
}
@@ -976,8 +1045,8 @@ public double getMobAttributeValue(@NotNull final LivingEntityWrapper lmEntity,
return result;
}
- public double getMobHealth(@NotNull final LivingEntityWrapper lmEntity){
- double result;
+ private double getMobHealth(@NotNull final LivingEntityWrapper lmEntity){
+ final double result;
synchronized (main.attributeSyncObject){
result = lmEntity.getLivingEntity().getHealth();
}
@@ -1007,7 +1076,7 @@ This is also ran in getLevellableState(EntityType), however it is important that
if (!(lmInterface instanceof LivingEntityWrapper))
return LevellableState.ALLOWED;
- LivingEntityWrapper lmEntity = (LivingEntityWrapper) lmInterface;
+ final LivingEntityWrapper lmEntity = (LivingEntityWrapper) lmInterface;
final LevellableState externalCompatResult = ExternalCompatibilityManager.checkAllExternalCompats(lmEntity, main);
if (externalCompatResult != LevellableState.ALLOWED)
@@ -1078,12 +1147,12 @@ public void applyLevelToMob(@NotNull final LivingEntityWrapper lmEntity, int lev
}
if (isSummoned) {
- SummonedMobPreLevelEvent summonedMobPreLevelEvent = new SummonedMobPreLevelEvent(lmEntity.getLivingEntity(), level);
+ final SummonedMobPreLevelEvent summonedMobPreLevelEvent = new SummonedMobPreLevelEvent(lmEntity.getLivingEntity(), level);
Bukkit.getPluginManager().callEvent(summonedMobPreLevelEvent);
if (summonedMobPreLevelEvent.isCancelled()) return;
} else {
- MobPreLevelEvent mobPreLevelEvent = new MobPreLevelEvent(lmEntity.getLivingEntity(), level, MobPreLevelEvent.LevelCause.NORMAL, additionalLevelInformation);
+ final MobPreLevelEvent mobPreLevelEvent = new MobPreLevelEvent(lmEntity.getLivingEntity(), level, MobPreLevelEvent.LevelCause.NORMAL, additionalLevelInformation);
Bukkit.getPluginManager().callEvent(mobPreLevelEvent);
if (mobPreLevelEvent.isCancelled()) return;
@@ -1095,7 +1164,7 @@ public void applyLevelToMob(@NotNull final LivingEntityWrapper lmEntity, int lev
}
}
- boolean hasNoLevelKey;
+ final boolean hasNoLevelKey;
synchronized (lmEntity.getLivingEntity().getPersistentDataContainer()) {
hasNoLevelKey = lmEntity.getPDC().has(main.namespaced_keys.noLevelKey, PersistentDataType.STRING);
}
@@ -1110,18 +1179,16 @@ public void applyLevelToMob(@NotNull final LivingEntityWrapper lmEntity, int lev
}
lmEntity.invalidateCache();
- String nbtData = lmEntity.nbtData != null ?
+ final List nbtDatas = lmEntity.nbtData != null && !lmEntity.nbtData.isEmpty() ?
lmEntity.nbtData : main.rulesManager.getRule_NBT_Data(lmEntity);
- if (nbtData != null && !ExternalCompatibilityManager.hasNBTAPI_Installed()){
+ if (!nbtDatas.isEmpty() && !ExternalCompatibilityManager.hasNBTAPI_Installed()){
if (!hasMentionedNBTAPI_Missing) {
Utils.logger.warning("NBT Data has been specified in customdrops.yml but required plugin NBTAPI is not installed!");
hasMentionedNBTAPI_Missing = true;
}
- nbtData = null;
+ nbtDatas.clear();
}
- final String finalNbtData = nbtData;
- final int creeperLevel = level;
// setting attributes should be only done in the main thread.
final BukkitRunnable applyAttribs = new BukkitRunnable() {
@@ -1144,20 +1211,35 @@ else if (lmEntity.getLivingEntity() instanceof Horse)
main.levelManager.applyLevelledAttributes(lmEntity, Addition.ATTRIBUTE_HORSE_JUMP_STRENGTH);
}
- if (finalNbtData != null) {
- NBTApplyResult result = NBTManager.applyNBT_Data_Mob(lmEntity, finalNbtData);
- if (result.hadException()) {
- if (lmEntity.summonedSender == null)
- Utils.logger.warning("Error applying NBT data to " + lmEntity.getTypeName() + ". Exception message: " + result.exceptionMessage);
- else
- lmEntity.summonedSender.sendMessage("Error applying NBT data to " + lmEntity.getTypeName() + ". Exception message: " + result.exceptionMessage);
+ if (!nbtDatas.isEmpty()) {
+ boolean hadSuccess = false;
+ final List allResults = new LinkedList<>();
+
+ for (final String nbtData : nbtDatas) {
+ final NBTApplyResult result = NBTManager.applyNBT_Data_Mob(lmEntity, nbtData);
+ if (result.hadException()) {
+ if (lmEntity.summonedSender == null) {
+ Utils.logger.warning(String.format(
+ "Error applying NBT data '%s' to %s. Exception message: %s",
+ nbtData, lmEntity.getNameIfBaby(), result.exceptionMessage));
+ }
+ else
+ lmEntity.summonedSender.sendMessage("Error applying NBT data to " + lmEntity.getNameIfBaby() + ". Exception message: " + result.exceptionMessage);
+ } else {
+ hadSuccess = true;
+ allResults.add(result);
+ }
+ }
+
+ if (hadSuccess && lmEntity.getMainInstance().companion.debugsEnabled.contains(DebugType.NBT_APPLY_SUCCESS)) {
+ final String changes = getNBT_DebugMessage(allResults);
+
+ Utils.debugLog(main, DebugType.NBT_APPLY_SUCCESS, "Applied NBT data to '" + lmEntity.getNameIfBaby() + "'. " + changes);
}
- else
- Utils.debugLog(main, DebugType.NBT_APPLY_SUCCESS, "Successfully applied NBT data to '" + lmEntity.getTypeName() + "'.");
}
if (lmEntity.getLivingEntity() instanceof Creeper)
- main.levelManager.applyCreeperBlastRadius(lmEntity, creeperLevel);
+ main.levelManager.applyCreeperBlastRadius(lmEntity);
lmEntity.free();
}
@@ -1170,7 +1252,7 @@ else if (lmEntity.getLivingEntity() instanceof Horse)
main.levelManager.updateNametag_WithDelay(lmEntity);
main.levelManager.applyLevelledEquipment(lmEntity, lmEntity.getMobLevel());
- MobPostLevelEvent.LevelCause levelCause = isSummoned ? MobPostLevelEvent.LevelCause.SUMMONED : MobPostLevelEvent.LevelCause.NORMAL;
+ final MobPostLevelEvent.LevelCause levelCause = isSummoned ? MobPostLevelEvent.LevelCause.SUMMONED : MobPostLevelEvent.LevelCause.NORMAL;
Bukkit.getPluginManager().callEvent(new MobPostLevelEvent(lmEntity, levelCause, additionalLevelInformation));
final StringBuilder sb = new StringBuilder();
@@ -1187,17 +1269,47 @@ else if (lmEntity.getLivingEntity() instanceof Horse)
Utils.debugLog(main, DebugType.APPLY_LEVEL_SUCCESS, sb.toString());
}
- private void getPlayersNearMob(final @NotNull LivingEntityWrapper lmEntity){
- final int checkDistance = main.helperSettings.getInt(main.settingsCfg, "async-task-max-blocks-from-player", 100);
- final List players = EntitySpawnListener.getPlayersNearMob(lmEntity.getLivingEntity(), checkDistance);
+ @NotNull
+ private String getNBT_DebugMessage(final @NotNull List results){
+ final StringBuilder sb = new StringBuilder();
+
+ for (final NBTApplyResult result : results) {
+ if (result.objectsAdded == null) continue;
+
+ for (int i = 0; i < result.objectsAdded.size(); i++) {
+ if (i > 0) sb.append(", ");
+ else sb.append("added: ");
+
+ sb.append(result.objectsAdded.get(i));
+ }
+ }
+
+ for (final NBTApplyResult result : results) {
+ if (result.objectsUpdated == null) continue;
+
+ for (int i = 0; i < result.objectsUpdated.size(); i++) {
+ if (i > 0 || sb.length() > 0) sb.append(", ");
+ if (i == 0) sb.append("updated: ");
+
+ sb.append(result.objectsUpdated.get(i));
+ }
+ }
+
+ for (final NBTApplyResult result : results) {
+ if (result.objectsRemoved == null) continue;
- for (final Player player : players){
- if (lmEntity.getLivingEntity().hasLineOfSight(player)){
- if (lmEntity.playersNeedingNametagCooldownUpdate == null)
- lmEntity.playersNeedingNametagCooldownUpdate = new HashSet<>();
- lmEntity.playersNeedingNametagCooldownUpdate.add(player);
+ for (int i = 0; i < result.objectsRemoved.size(); i++) {
+ if (i > 0 || sb.length() > 0) sb.append(", ");
+ if (i == 0) sb.append("removed: ");
+
+ sb.append(result.objectsRemoved.get(i));
}
}
+
+ if (sb.length() > 0)
+ return sb.toString();
+ else
+ return "";
}
/**
@@ -1273,7 +1385,7 @@ public void removeLevel(@NotNull final LivingEntityWrapper lmEntity) {
// reset attributes
synchronized (main.attributeSyncObject) {
- for (Attribute attribute : Attribute.values()) {
+ for (final Attribute attribute : Attribute.values()) {
final AttributeInstance attInst = lmEntity.getLivingEntity().getAttribute(attribute);
if (attInst == null) continue;
diff --git a/src/main/java/me/lokka30/levelledmobs/managers/MobDataManager.java b/src/main/java/me/lokka30/levelledmobs/managers/MobDataManager.java
index e7d387163..70049da9c 100644
--- a/src/main/java/me/lokka30/levelledmobs/managers/MobDataManager.java
+++ b/src/main/java/me/lokka30/levelledmobs/managers/MobDataManager.java
@@ -36,7 +36,7 @@ public MobDataManager(final LevelledMobs main) {
}
@Nullable
- public Object getAttributeDefaultValue(@NotNull final LivingEntityWrapper lmEntity, final Attribute attribute) {
+ private Object getAttributeDefaultValue(@NotNull final LivingEntityWrapper lmEntity, final Attribute attribute) {
if (lmEntity.isMobTamed()){
// if the tamed variant in the cfg then use it, otherwise check for untamed path
final String tamedPath = "TAMED_" + lmEntity.getTypeName() + "." + attribute;
@@ -50,7 +50,7 @@ public Object getAttributeDefaultValue(@NotNull final LivingEntityWrapper lmEnti
null;
}
- public final boolean isLevelledDropManaged(final EntityType entityType, @NotNull final Material material) {
+ final boolean isLevelledDropManaged(final EntityType entityType, @NotNull final Material material) {
// Head drops
if (material.toString().endsWith("_HEAD") || material.toString().endsWith("_SKULL")) {
if (!main.helperSettings.getBoolean(main.settingsCfg, "mobs-multiply-head-drops"))
@@ -61,7 +61,7 @@ public final boolean isLevelledDropManaged(final EntityType entityType, @NotNull
return main.dropsCfg.getStringList(entityType.toString()).contains(material.toString());
}
- public void setAdditionsForLevel(@NotNull final LivingEntityWrapper lmEntity, final @NotNull Attribute attribute, final Addition addition) {
+ void setAdditionsForLevel(@NotNull final LivingEntityWrapper lmEntity, final @NotNull Attribute attribute, final Addition addition) {
final boolean useStaticValues = main.helperSettings.getBoolean(main.settingsCfg, "attributes-use-preset-base-values");
final double defaultValue = useStaticValues ?
(double) Objects.requireNonNull(getAttributeDefaultValue(lmEntity, attribute)) :
@@ -105,12 +105,11 @@ public void setAdditionsForLevel(@NotNull final LivingEntityWrapper lmEntity, fi
try {
if (lmEntity.getLivingEntity().getHealth() <= 0.0) return;
lmEntity.getLivingEntity().setHealth(newHealth);
- } catch (IllegalArgumentException ignored) { }
-
+ } catch (final IllegalArgumentException ignored) { }
}
}
- public final double getAdditionsForLevel(final LivingEntityWrapper lmEntity, final Addition addition, double defaultValue) {
+ public final double getAdditionsForLevel(final LivingEntityWrapper lmEntity, final Addition addition, final double defaultValue) {
final double maxLevel = main.rulesManager.getRule_MobMaxLevel(lmEntity);
double attributeValue = 0;
diff --git a/src/main/java/me/lokka30/levelledmobs/managers/MobHeadManager.java b/src/main/java/me/lokka30/levelledmobs/managers/MobHeadManager.java
index eb23087df..c26751ea4 100644
--- a/src/main/java/me/lokka30/levelledmobs/managers/MobHeadManager.java
+++ b/src/main/java/me/lokka30/levelledmobs/managers/MobHeadManager.java
@@ -9,8 +9,11 @@
import me.lokka30.levelledmobs.LevelledMobs;
import me.lokka30.levelledmobs.customdrops.CustomDropItem;
import me.lokka30.levelledmobs.misc.LivingEntityWrapper;
+import me.lokka30.levelledmobs.misc.PaperUtils;
+import me.lokka30.levelledmobs.misc.SpigotUtils;
import me.lokka30.levelledmobs.misc.Utils;
-import me.lokka30.microlib.MessageUtils;
+import me.lokka30.microlib.messaging.MessageUtils;
+import me.lokka30.microlib.other.VersionUtils;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.configuration.file.YamlConfiguration;
@@ -43,6 +46,7 @@ public MobHeadManager(final LevelledMobs main){
public void loadTextures(@NotNull final YamlConfiguration textureData){
mobMap = new LinkedHashMap<>();
+ //noinspection unchecked
final List> lst = (List>) textureData.getList("Mobs");
if (lst == null) return;
@@ -55,15 +59,15 @@ public void loadTextures(@NotNull final YamlConfiguration textureData){
mob.id = (String) item.get("ID");
mob.textureCode = (String) item.get("Texture");
- EntityType entityType;
+ final EntityType entityType;
try{
entityType = EntityType.valueOf(mob.name.toUpperCase());
- } catch (Exception e){
+ } catch (final Exception e){
//Utils.logger.warning("Invalid mob in textures.yml: " + mob.name);
continue;
}
- Map infos = this.mobMap.computeIfAbsent(
+ final Map infos = this.mobMap.computeIfAbsent(
entityType, k -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER));
infos.put(mob.variant == null ? "" : mob.variant, mob);
}
@@ -71,8 +75,8 @@ public void loadTextures(@NotNull final YamlConfiguration textureData){
public ItemStack getMobHeadFromPlayerHead(final ItemStack playerHead, final LivingEntityWrapper lmEntity, @NotNull final CustomDropItem dropItem){
- String textureCode;
- UUID id;
+ final String textureCode;
+ final UUID id;
MobDataInfo mobData = null;
if (dropItem.customPlayerHeadId == null) {
@@ -80,10 +84,9 @@ public ItemStack getMobHeadFromPlayerHead(final ItemStack playerHead, final Livi
if (vanillaMaterial != Material.AIR) {
final ItemStack newItem = new ItemStack(vanillaMaterial, playerHead.getAmount());
final ItemMeta meta = playerHead.getItemMeta();
- if (meta != null) {
- ItemMeta newMeta = meta.clone();
- newItem.setItemMeta(meta);
- }
+ if (meta != null)
+ newItem.setItemMeta(meta.clone());
+
return newItem;
}
@@ -95,14 +98,14 @@ public ItemStack getMobHeadFromPlayerHead(final ItemStack playerHead, final Livi
final Map mobDatas = this.mobMap.get(lmEntity.getEntityType());
if (mobDatas.size() > 1){
- MobDataInfo foundMob = getMobVariant(mobDatas, lmEntity);
+ final MobDataInfo foundMob = getMobVariant(mobDatas, lmEntity);
if (foundMob != null) mobData = foundMob;
}
if (mobData == null){
// grab first one
- for (final String variant : mobDatas.keySet()){
- mobData = mobDatas.get(variant);
+ for (final MobDataInfo mobDataInfo : mobDatas.values()){
+ mobData = mobDataInfo;
break;
}
}
@@ -113,7 +116,7 @@ public ItemStack getMobHeadFromPlayerHead(final ItemStack playerHead, final Livi
try {
id = UUID.fromString(mobData.id);
- } catch (IllegalArgumentException e) {
+ } catch (final IllegalArgumentException e) {
Utils.logger.warning("mob: " + lmEntity.getTypeName() + ", exception getting UUID for mob head. " + e.getMessage());
return playerHead;
}
@@ -126,15 +129,15 @@ public ItemStack getMobHeadFromPlayerHead(final ItemStack playerHead, final Livi
if (textureCode != null)
profile.getProperties().put("textures", new Property("textures", textureCode));
- SkullMeta meta = (SkullMeta) playerHead.getItemMeta();
+ final SkullMeta meta = (SkullMeta) playerHead.getItemMeta();
if (meta == null) return playerHead;
- Field profileField;
+ final Field profileField;
try {
profileField = meta.getClass().getDeclaredField("profile");
profileField.setAccessible(true);
profileField.set(meta, profile);
- } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e1) {
+ } catch (final NoSuchFieldException | IllegalArgumentException | IllegalAccessException e1) {
Utils.logger.warning("Unable to set meta data in profile class for mob " + lmEntity.getTypeName());
}
@@ -144,17 +147,13 @@ public ItemStack getMobHeadFromPlayerHead(final ItemStack playerHead, final Livi
String killerName = "";
final Player killerPlayer = lmEntity.getLivingEntity().getKiller();
if (killerPlayer != null)
- killerName = killerPlayer.getDisplayName();
- final boolean useCustomNameForNametags = main.helperSettings.getBoolean(main.settingsCfg, "use-customname-for-mob-nametags");
- final String overridenName = main.rulesManager.getRule_EntityOverriddenName(lmEntity, useCustomNameForNametags);
- final String mobName = overridenName == null ?
- Utils.capitalize(lmEntity.getTypeName().replace("_", " ")) :
- overridenName;
- useName = main.levelManager.replaceStringPlaceholders(dropItem.customName, lmEntity, mobName);
+ killerName = VersionUtils.isRunningPaper() ?
+ PaperUtils.getPlayerDisplayName(killerPlayer) : SpigotUtils.getPlayerDisplayName(killerPlayer);
+ useName = main.levelManager.replaceStringPlaceholders(dropItem.customName, lmEntity);
useName = MessageUtils.colorizeAll(useName);
- String displayName = lmEntity.getLivingEntity().getCustomName() == null ?
+ final String displayName = lmEntity.getLivingEntity().getCustomName() == null ?
useName : lmEntity.getLivingEntity().getCustomName();
useName = useName.replace("%displayname%", displayName);
@@ -163,7 +162,11 @@ public ItemStack getMobHeadFromPlayerHead(final ItemStack playerHead, final Livi
} else
useName = "Mob Head";
- meta.setDisplayName(useName);
+ if (VersionUtils.isRunningPaper())
+ PaperUtils.updateItemDisplayName(meta, useName);
+ else
+ SpigotUtils.updateItemDisplayName(meta, useName);
+
playerHead.setItemMeta(meta);
return playerHead;
@@ -200,54 +203,54 @@ private MobDataInfo getMobVariant(final Map mobDatas, @NotN
}
// uncharged creepers already got processed
- if (et.equals(EntityType.CREEPER))
+ if (et == EntityType.CREEPER)
return mobDatas.get("Charged");
- if (et.equals(EntityType.CAT)){
+ if (et == EntityType.CAT){
final Cat cat = (Cat) livingEntity;
return mobDatas.get(cat.getCatType().name());
}
- if (et.equals(EntityType.FOX)){
- if (((Fox) livingEntity).getFoxType().equals(Fox.Type.RED))
+ if (et == EntityType.FOX){
+ if (((Fox) livingEntity).getFoxType() == Fox.Type.RED)
return mobDatas.get("Normal");
else
return mobDatas.get("Snow");
}
- if (et.equals(EntityType.HORSE)){
+ if (et == EntityType.HORSE){
final Horse horse = (Horse) livingEntity;
return mobDatas.get(horse.getColor().name());
}
- if (et.equals(EntityType.LLAMA)){
+ if (et == EntityType.LLAMA){
final Llama llama = (Llama) livingEntity;
return mobDatas.get(llama.getColor().name());
}
- if (et.equals(EntityType.MUSHROOM_COW)){
+ if (et == EntityType.MUSHROOM_COW){
final MushroomCow mushroomCow = (MushroomCow) livingEntity;
return mobDatas.get(
- mushroomCow.getVariant().equals(MushroomCow.Variant.RED) ?
+ mushroomCow.getVariant() == MushroomCow.Variant.RED ?
"" : "Brown"
);
}
- if (et.equals(EntityType.PANDA))
+ if (et == EntityType.PANDA)
return mobDatas.get(((Panda) livingEntity).getMainGene().name());
- if (et.equals(EntityType.RABBIT))
+ if (et == EntityType.RABBIT)
return mobDatas.get(((Rabbit) livingEntity).getRabbitType().name());
- if (et.equals(EntityType.VILLAGER)){
+ if (et == EntityType.VILLAGER){
final Villager.Profession profession = ((Villager) livingEntity).getProfession();
- if (profession.equals(Villager.Profession.NONE) || profession.equals(Villager.Profession.NITWIT))
+ if (profession == Villager.Profession.NONE || profession == Villager.Profession.NITWIT)
return mobDatas.get("");
else
return mobDatas.get(profession.name());
}
- if (et.equals(EntityType.WOLF)){
+ if (et == EntityType.WOLF){
return mobDatas.get(
lmEntity.isMobTamed() ?
"Tamed" : "Wild"
@@ -259,10 +262,10 @@ private MobDataInfo getMobVariant(final Map mobDatas, @NotN
}
private static class MobDataInfo{
- public String name;
- public String variant;
- public String displayName;
- public String id;
- public String textureCode;
+ String name;
+ String variant;
+ String displayName;
+ String id;
+ String textureCode;
}
}
diff --git a/src/main/java/me/lokka30/levelledmobs/managers/MobsQueueManager.java b/src/main/java/me/lokka30/levelledmobs/managers/MobsQueueManager.java
index 0e9a09478..942b57b86 100644
--- a/src/main/java/me/lokka30/levelledmobs/managers/MobsQueueManager.java
+++ b/src/main/java/me/lokka30/levelledmobs/managers/MobsQueueManager.java
@@ -8,6 +8,7 @@
import me.lokka30.levelledmobs.misc.QueueItem;
import me.lokka30.levelledmobs.misc.Utils;
import org.bukkit.scheduler.BukkitRunnable;
+import org.jetbrains.annotations.NotNull;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@@ -40,7 +41,7 @@ public void start(){
public void run() {
try {
main();
- } catch (InterruptedException ignored) {
+ } catch (final InterruptedException ignored) {
isRunning = false;
}
Utils.logger.info("Mob processing queue Manager has exited");
@@ -54,7 +55,7 @@ public void stop(){
doThread = false;
}
- public void addToQueue(final QueueItem item) {
+ public void addToQueue(final @NotNull QueueItem item) {
if (item.lmEntity.getLivingEntity() == null) return;
item.lmEntity.inUseCount.getAndIncrement();
@@ -75,8 +76,7 @@ private void main() throws InterruptedException{
lastEntityType = item.lmEntity.getNameIfBaby();
main.levelManager.entitySpawnListener.preprocessMob(item.lmEntity, item.event);
}
- }
- catch (Exception e){
+ } catch (final Exception e){
Utils.logger.error("Got exception while processing " + (lastEntityType != null ? lastEntityType : "(unknown)"));
e.printStackTrace();
}
diff --git a/src/main/java/me/lokka30/levelledmobs/managers/NBTManager.java b/src/main/java/me/lokka30/levelledmobs/managers/NBTManager.java
index 97d39cbb7..6b86e85f2 100644
--- a/src/main/java/me/lokka30/levelledmobs/managers/NBTManager.java
+++ b/src/main/java/me/lokka30/levelledmobs/managers/NBTManager.java
@@ -4,14 +4,21 @@
package me.lokka30.levelledmobs.managers;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
import de.tr7zw.nbtapi.NBTContainer;
import de.tr7zw.nbtapi.NBTEntity;
import de.tr7zw.nbtapi.NBTItem;
import me.lokka30.levelledmobs.customdrops.CustomDropItem;
+import me.lokka30.levelledmobs.misc.DebugType;
import me.lokka30.levelledmobs.misc.LivingEntityWrapper;
import me.lokka30.levelledmobs.misc.NBTApplyResult;
import org.jetbrains.annotations.NotNull;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.TreeMap;
+
/**
* @author stumper66
* @since 3.1.0
@@ -26,14 +33,14 @@ public static NBTApplyResult applyNBT_Data_Item(@NotNull final CustomDropItem it
try {
nbtent.mergeCompound(new NBTContainer(nbtStuff));
result.itemStack = nbtent.getItem();
- } catch (Exception e) {
+ } catch (final Exception e) {
result.exceptionMessage = e.getMessage();
}
return result;
}
- public static NBTApplyResult applyNBT_Data_Mob(@NotNull final LivingEntityWrapper lmEntity, @NotNull final String nbtStuff) {
+ static @NotNull NBTApplyResult applyNBT_Data_Mob(@NotNull final LivingEntityWrapper lmEntity, @NotNull final String nbtStuff) {
final NBTApplyResult result = new NBTApplyResult();
try {
@@ -42,12 +49,51 @@ public static NBTApplyResult applyNBT_Data_Mob(@NotNull final LivingEntityWrappe
nbtent.mergeCompound(new NBTContainer(nbtStuff));
final String jsonAfter = nbtent.toString();
+ if (lmEntity.getMainInstance().companion.debugsEnabled.contains(DebugType.NBT_APPLY_SUCCESS))
+ showChangedJson(jsonBefore, jsonAfter, result);
+
if (jsonBefore.equals(jsonAfter))
result.exceptionMessage = "No NBT data changed. Make sure you have used proper NBT strings";
- } catch (Exception e) {
+ } catch (final Exception e) {
result.exceptionMessage = e.getMessage();
}
return result;
}
+
+ private static void showChangedJson(final String jsonBefore, final String jsonAfter, final NBTApplyResult applyResult){
+ final Map objectsBefore = new TreeMap<>();
+ final Map objectsAfter = new TreeMap<>();
+ final JsonObject jsonObjectBefore = JsonParser.parseString(jsonBefore).getAsJsonObject();
+ final JsonObject jsonObjectAfter = JsonParser.parseString(jsonAfter).getAsJsonObject();
+
+ try {
+ for (final String key : jsonObjectBefore.keySet()) {
+ objectsBefore.put(key, jsonObjectBefore.get(key).toString());
+ }
+ for (final String key : jsonObjectAfter.keySet()) {
+ objectsAfter.put(key, jsonObjectAfter.get(key).toString());
+ }
+ } catch (final Exception e){
+ e.printStackTrace();
+ return;
+ }
+
+ for (final String key : jsonObjectAfter.keySet()){
+ final String value = jsonObjectAfter.get(key).toString();
+
+ if (objectsBefore.containsKey(key) && objectsAfter.containsKey(key) && !objectsBefore.get(key).equals(value)) {
+ if (applyResult.objectsUpdated == null) applyResult.objectsUpdated = new LinkedList<>();
+ applyResult.objectsUpdated.add(key + ":" + value);
+ }
+ else if (!objectsBefore.containsKey(key) && objectsAfter.containsKey(key)) {
+ if (applyResult.objectsAdded == null) applyResult.objectsAdded = new LinkedList<>();
+ applyResult.objectsAdded.add(key + ":" + value);
+ }
+ else if (objectsBefore.containsKey(key) && !objectsAfter.containsKey(key)) {
+ if (applyResult.objectsRemoved == null) applyResult.objectsRemoved = new LinkedList<>();
+ applyResult.objectsRemoved.add(key + ":" + value);
+ }
+ }
+ }
}
diff --git a/src/main/java/me/lokka30/levelledmobs/managers/NametagQueueManager.java b/src/main/java/me/lokka30/levelledmobs/managers/NametagQueueManager.java
index 08c2ccfe8..e20219330 100644
--- a/src/main/java/me/lokka30/levelledmobs/managers/NametagQueueManager.java
+++ b/src/main/java/me/lokka30/levelledmobs/managers/NametagQueueManager.java
@@ -54,7 +54,7 @@ public void start(){
public void run() {
try {
main();
- } catch (InterruptedException ignored) {
+ } catch (final InterruptedException ignored) {
isRunning = false;
}
Utils.logger.info("Nametag update queue Manager has exited");
@@ -68,7 +68,7 @@ public void stop(){
doThread = false;
}
- public void addToQueue(final @NotNull QueueItem item) {
+ void addToQueue(final @NotNull QueueItem item) {
if (Bukkit.getOnlinePlayers().size() == 0) return;
if (item.lmEntity.getLivingEntity() == null ||
main.rulesManager.getRule_CreatureNametagVisbility(item.lmEntity).contains(NametagVisibilityEnum.DISABLED))
@@ -92,8 +92,7 @@ private void main() throws InterruptedException{
try {
lastEntityType = item.lmEntity.getNameIfBaby();
processItem(item);
- }
- catch (Exception e){
+ } catch (final Exception e){
Utils.logger.error("Got exception while processing nametag updates on " + (lastEntityType != null ? lastEntityType : "(unknown)"));
e.printStackTrace();
}
@@ -108,7 +107,7 @@ private void main() throws InterruptedException{
private void processItem(final @NotNull QueueItem item){
final int nametagTimerResetTime = item.lmEntity.getNametagCooldownTime();
- if (nametagTimerResetTime > 0 && !"".equals(item.nametag)) {
+ if (nametagTimerResetTime > 0 && !Utils.isNullOrEmpty(item.nametag)) {
synchronized (NametagTimerChecker.nametagTimer_Lock) {
final Map> nametagCooldownQueue = main.nametagTimerChecker.getNametagCooldownQueue();
@@ -123,21 +122,22 @@ private void processItem(final @NotNull QueueItem item){
}
// if any players already have a cooldown on this mob then don't remove the cooldown
- for (final Player player : nametagCooldownQueue.keySet()){
+ for (final Map.Entry> coolDown : nametagCooldownQueue.entrySet()){
+ final Player player = coolDown.getKey();
if (item.lmEntity.playersNeedingNametagCooldownUpdate.contains(player)) continue;
- if (nametagCooldownQueue.get(player).containsKey(item.lmEntity.getLivingEntity()))
+ if (coolDown.getValue().containsKey(item.lmEntity.getLivingEntity()))
item.lmEntity.playersNeedingNametagCooldownUpdate.add(player);
}
}
else{
// if there's any existing cooldowns we'll use them
- for (final Player player : nametagCooldownQueue.keySet()){
- if (nametagCooldownQueue.get(player).containsKey(item.lmEntity.getLivingEntity())) {
+ for (final Map.Entry> coolDown : nametagCooldownQueue.entrySet()){
+ if (coolDown.getValue().containsKey(item.lmEntity.getLivingEntity())) {
if (item.lmEntity.playersNeedingNametagCooldownUpdate == null)
item.lmEntity.playersNeedingNametagCooldownUpdate = new HashSet<>();
- item.lmEntity.playersNeedingNametagCooldownUpdate.add(player);
+ item.lmEntity.playersNeedingNametagCooldownUpdate.add(coolDown.getKey());
}
}
}
@@ -181,17 +181,17 @@ private void updateNametag(final @NotNull LivingEntityWrapper lmEntity, final St
try {
dataWatcher = WrappedDataWatcher.getEntityWatcher(lmEntity.getLivingEntity()).deepClone();
- } catch (ConcurrentModificationException ex) {
+ } catch (final ConcurrentModificationException ex) {
Utils.debugLog(main, DebugType.UPDATE_NAMETAG_FAIL, "&bConcurrentModificationException &7caught, skipping nametag update of &b" + lmEntity.getLivingEntity().getName() + "&7.");
return;
}
try {
chatSerializer = WrappedDataWatcher.Registry.getChatComponentSerializer(true);
- } catch (ConcurrentModificationException ex) {
+ } catch (final ConcurrentModificationException ex) {
Utils.debugLog(main, DebugType.UPDATE_NAMETAG_FAIL, "&bConcurrentModificationException &7caught, skipping nametag update of &b" + lmEntity.getLivingEntity().getName() + "&7.");
return;
- } catch (IllegalArgumentException ex) {
+ } catch (final IllegalArgumentException ex) {
Utils.debugLog(main, DebugType.UPDATE_NAMETAG_FAIL, "Registry is empty (&bIllegalArgumentException&7 caught), skipping nametag update of &b" + lmEntity.getLivingEntity().getName() + "&7.");
return;
}
@@ -209,7 +209,7 @@ private void updateNametag(final @NotNull LivingEntityWrapper lmEntity, final St
else {
final List nametagVisibilityEnum = main.rulesManager.getRule_CreatureNametagVisbility(lmEntity);
final boolean doAlwaysVisible = i == 1 ||
- !"".equals(nametag) && lmEntity.getLivingEntity().isCustomNameVisible() ||
+ !nametag.isEmpty() && lmEntity.getLivingEntity().isCustomNameVisible() ||
nametagVisibilityEnum.contains(NametagVisibilityEnum.ALWAYS_ON);
dataWatcher.setObject(objectIndex, doAlwaysVisible);
@@ -227,8 +227,7 @@ private void updateNametag(final @NotNull LivingEntityWrapper lmEntity, final St
if (!sendPacket(player, lmEntity, packet)) return;
}
- }
- else{
+ } else {
// these players are getting always on nametags
for (final Player player : lmEntity.playersNeedingNametagCooldownUpdate)
if (!sendPacket(player, lmEntity, packet)) return;
@@ -244,9 +243,9 @@ private boolean sendPacket(final @NotNull Player player, final LivingEntityWrapp
try {
Utils.debugLog(main, DebugType.UPDATE_NAMETAG_SUCCESS, "Nametag packet sent for &b" + lmEntity.getLivingEntity().getName() + "&7 to &b" + player.getName() + "&7.");
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);
- } catch (IllegalArgumentException ex) {
+ } catch (final IllegalArgumentException ex) {
Utils.debugLog(main, DebugType.UPDATE_NAMETAG_FAIL, "&bIllegalArgumentException&7 caught whilst trying to sendServerPacket");
- } catch (InvocationTargetException ex) {
+ } catch (final InvocationTargetException ex) {
Utils.logger.error("Unable to update nametag packet for player &b" + player.getName() + "&7; Stack trace:");
ex.printStackTrace();
}
diff --git a/src/main/java/me/lokka30/levelledmobs/managers/PlaceholderApiIntegration.java b/src/main/java/me/lokka30/levelledmobs/managers/PlaceholderApiIntegration.java
index 9b94c5e9a..1f466cb66 100644
--- a/src/main/java/me/lokka30/levelledmobs/managers/PlaceholderApiIntegration.java
+++ b/src/main/java/me/lokka30/levelledmobs/managers/PlaceholderApiIntegration.java
@@ -8,7 +8,12 @@
import me.lokka30.levelledmobs.LevelledMobs;
import me.lokka30.levelledmobs.misc.LastMobKilledInfo;
import me.lokka30.levelledmobs.misc.LivingEntityWrapper;
+import me.lokka30.levelledmobs.misc.Utils;
+import org.bukkit.Location;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -87,6 +92,8 @@ public String onPlaceholderRequest(final Player player, final @NotNull String id
return getLevelFromPlayer(player);
else if ("displayname".equalsIgnoreCase(identifier))
return getDisplaynameFromPlayer(player);
+ else if ("mob-target".equalsIgnoreCase(identifier))
+ return getMobNametagWithinPlayerSight(player);
return null;
}
@@ -97,7 +104,7 @@ private String getLevelFromPlayer(final @NotNull Player player){
final LastMobKilledInfo mobInfo = this.mobsByPlayerTracking.get(player.getUniqueId());
return mobInfo.entityLevel == null ?
- "" : mobInfo.entityLevel + "";
+ "" : String.valueOf(mobInfo.entityLevel);
}
@NotNull
@@ -108,4 +115,50 @@ private String getDisplaynameFromPlayer(final @NotNull Player player){
return mobInfo == null || mobInfo.entityName == null ?
"" : mobInfo.entityName;
}
+
+ @NotNull
+ private String getMobNametagWithinPlayerSight(final @Nullable Player player){
+ if (player == null) return "";
+
+ final LivingEntity targetMob = getMobBeingLookedAt(player);
+ if (targetMob == null) return "";
+
+ final LivingEntityWrapper lmEntity = LivingEntityWrapper.getInstance(targetMob, main);
+ String nametag = main.rulesManager.getRule_Nametag_Placeholder(lmEntity);
+ if (!Utils.isNullOrEmpty(nametag)){
+ final boolean useCustomNameForNametags = main.helperSettings.getBoolean(main.settingsCfg, "use-customname-for-mob-nametags");
+ nametag = main.levelManager.updateNametag(lmEntity, nametag, useCustomNameForNametags);
+
+ if ("disabled".equalsIgnoreCase(nametag)) return "";
+ }
+
+ if (Utils.isNullOrEmpty(nametag) && lmEntity.isLevelled())
+ nametag = main.levelManager.getNametag(lmEntity, false);
+
+ lmEntity.free();
+
+ return nametag != null ?
+ nametag : "";
+ }
+
+ @Nullable
+ private LivingEntity getMobBeingLookedAt(final @NotNull Player player){
+ LivingEntity livingEntity = null;
+ final Location eye = player.getEyeLocation();
+ final int maxBlocks = main.helperSettings.getInt(main.settingsCfg, "nametag-placeholder-maxblocks", 30);
+
+ for(final Entity entity : player.getNearbyEntities(maxBlocks, maxBlocks, maxBlocks)){
+ if (!(entity instanceof LivingEntity)) continue;
+
+ final LivingEntity le = (LivingEntity) entity;
+ final Vector toEntity = le.getEyeLocation().toVector().subtract(eye.toVector());
+ final double dot = toEntity.normalize().dot(eye.getDirection());
+ if (dot >= 0.975D) {
+ livingEntity = le;
+ break;
+ }
+ }
+
+ return livingEntity;
+ }
}
diff --git a/src/main/java/me/lokka30/levelledmobs/managers/WorldGuardIntegration.java b/src/main/java/me/lokka30/levelledmobs/managers/WorldGuardIntegration.java
index 922de18df..02b0e1274 100644
--- a/src/main/java/me/lokka30/levelledmobs/managers/WorldGuardIntegration.java
+++ b/src/main/java/me/lokka30/levelledmobs/managers/WorldGuardIntegration.java
@@ -12,9 +12,7 @@
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import me.lokka30.levelledmobs.LivingEntityInterface;
-import org.bukkit.Location;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -26,82 +24,7 @@
* @since 2.4.0
*/
public class WorldGuardIntegration {
-
- public WorldGuardIntegration() {
-
- }
-
- //Get all regions at an Entities' location.
- @NotNull
- public List getRegionSet(@NotNull final LivingEntityInterface lmInterface) {
- final List results = new LinkedList<>();
- final Location location = lmInterface.getLocation();
-
- final RegionContainer regionContainer = WorldGuard.getInstance().getPlatform().getRegionContainer();
- final RegionManager regionManager = regionContainer.get(BukkitAdapter.adapt(lmInterface.getWorld()));
-
- if (regionManager == null) return results;
-
- final ProtectedRegion globalRegion = regionManager.getRegion("__global__");
- if (location.getWorld() == null) {
- if (globalRegion != null) results.add(globalRegion);
- return results;
- }
-
- final BlockVector3 blockVector = BlockVector3.at(location.getX(), location.getY(), location.getZ());
- if (globalRegion != null) results.add(globalRegion);
- for (final ProtectedRegion region : regionManager.getApplicableRegions(blockVector))
- results.add(region);
-
- return results;
- }
-
- // Get all regions at a location
- @NotNull
- public List getRegionSet(@NotNull final Location location) {
- final List results = new LinkedList<>();
- if (location.getWorld() == null) return results;
-
- final RegionContainer regionContainer = WorldGuard.getInstance().getPlatform().getRegionContainer();
- final RegionManager regionManager = regionContainer.get(BukkitAdapter.adapt(location.getWorld()));
-
- if (regionManager == null) return results;
-
- final ProtectedRegion globalRegion = regionManager.getRegion("__global__");
- if (location.getWorld() == null) {
- if (globalRegion != null) results.add(globalRegion);
- return results;
- }
-
- final BlockVector3 blockVector = BlockVector3.at(location.getX(), location.getY(), location.getZ());
- final ApplicableRegionSet regionSet = regionManager.getApplicableRegions(blockVector);
- if (globalRegion != null) results.add(globalRegion);
- for (final ProtectedRegion region : regionSet)
- results.add(region);
-
- return results;
- }
-
-
- //Sorts a RegionSet by priority, lowest to highest.
- @Nullable
- public ProtectedRegion[] sortRegionsByPriority(final List regionSet) {
- if (regionSet == null) return null;
-
- ProtectedRegion[] protectedRegions = new ProtectedRegion[0];
-
- if (regionSet.size() == 0) {
- return protectedRegions;
- } else if (regionSet.size() == 1) {
- protectedRegions = new ProtectedRegion[1];
- return regionSet.toArray(protectedRegions);
- }
-
- final List protectedRegionList = new ArrayList<>(regionSet);
- protectedRegionList.sort(Comparator.comparingInt(ProtectedRegion::getPriority));
-
- return protectedRegionList.toArray(protectedRegions);
- }
+ private WorldGuardIntegration(){}
@NotNull
public static List getWorldGuardRegionsForLocation(@NotNull final LivingEntityInterface lmInterface) {
diff --git a/src/main/java/me/lokka30/levelledmobs/misc/CachedModalList.java b/src/main/java/me/lokka30/levelledmobs/misc/CachedModalList.java
index b7920ef03..dbbea9b12 100644
--- a/src/main/java/me/lokka30/levelledmobs/misc/CachedModalList.java
+++ b/src/main/java/me/lokka30/levelledmobs/misc/CachedModalList.java
@@ -17,6 +17,7 @@
* @author stumper66
* @since 3.0.0
*/
+@SuppressWarnings("unchecked")
public class CachedModalList> implements Cloneable {
public CachedModalList(){
this.allowedList = new TreeSet<>();
@@ -110,6 +111,7 @@ public String toString(){
return sb.toString();
}
+ @SuppressWarnings("unused")
public boolean isWhitelist(){
return (!this.allowedList.isEmpty() || !this.allowedGroups.isEmpty()) &&
(this.excludedList.isEmpty() && this.excludedGroups.isEmpty());
@@ -128,14 +130,14 @@ public Object clone(){
copy.allowedGroups = (TreeSet) ((TreeSet) (this.allowedGroups)).clone();
copy.excludedList = (TreeSet) ((TreeSet) (this.excludedList)).clone();
copy.excludedGroups = (TreeSet) ((TreeSet) (this.excludedGroups)).clone();
- } catch (CloneNotSupportedException e) {
+ } catch (final CloneNotSupportedException e) {
e.printStackTrace();
}
return copy;
}
- public void mergeCachedModal(@NotNull CachedModalList> cachedModalList){
+ public void mergeCachedModal(@NotNull final CachedModalList> cachedModalList){
this.allowedList.addAll((Collection extends T>) cachedModalList.allowedList);
this.excludedList.addAll((Collection extends T>) cachedModalList.excludedList);
diff --git a/src/main/java/me/lokka30/levelledmobs/misc/ConfigUtils.java b/src/main/java/me/lokka30/levelledmobs/misc/ConfigUtils.java
index e386b2a6e..22ca4edce 100644
--- a/src/main/java/me/lokka30/levelledmobs/misc/ConfigUtils.java
+++ b/src/main/java/me/lokka30/levelledmobs/misc/ConfigUtils.java
@@ -5,7 +5,7 @@
package me.lokka30.levelledmobs.misc;
import me.lokka30.levelledmobs.LevelledMobs;
-import me.lokka30.microlib.MessageUtils;
+import me.lokka30.microlib.messaging.MessageUtils;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
@@ -20,8 +20,8 @@
*/
public class ConfigUtils {
- public static int SETTINGS_CREEPER_MAX_RADIUS;
- public static int SETTINGS_SPAWN_DISTANCE_FROM_PLAYER;
+ private static int SETTINGS_CREEPER_MAX_RADIUS;
+ private static int SETTINGS_SPAWN_DISTANCE_FROM_PLAYER;
private final LevelledMobs main;
@@ -31,7 +31,6 @@ public ConfigUtils(final LevelledMobs main) {
public boolean debugEntityDamageWasEnabled = false;
public boolean chunkLoadListenerWasEnabled = false;
- public boolean mythicMobsWasEnabled = false;
public boolean playerLevellingEnabled = false;
public void load() {
diff --git a/src/main/java/me/lokka30/levelledmobs/misc/Cooldown.java b/src/main/java/me/lokka30/levelledmobs/misc/Cooldown.java
index 6460e4d40..e1e721452 100644
--- a/src/main/java/me/lokka30/levelledmobs/misc/Cooldown.java
+++ b/src/main/java/me/lokka30/levelledmobs/misc/Cooldown.java
@@ -4,6 +4,8 @@
package me.lokka30.levelledmobs.misc;
+import org.jetbrains.annotations.NotNull;
+
/**
* This class is used to put cooldowns on certain actions,
* on certain in-game objects - e.g. clicking entities or blocks.
@@ -39,7 +41,7 @@ public Cooldown(final long startingTime, final String identifier) {
* @param identifier ID to check if this cooldown has the same ID.
* @return if the IDs match.
*/
- public boolean doesCooldownBelongToIdentifier(final String identifier) {
+ public boolean doesCooldownBelongToIdentifier(final @NotNull String identifier) {
return identifier.equals(this.identifier);
}
diff --git a/src/main/java/me/lokka30/levelledmobs/misc/DebugCreator.java b/src/main/java/me/lokka30/levelledmobs/misc/DebugCreator.java
index 7556a05d9..5774e6b16 100644
--- a/src/main/java/me/lokka30/levelledmobs/misc/DebugCreator.java
+++ b/src/main/java/me/lokka30/levelledmobs/misc/DebugCreator.java
@@ -29,7 +29,7 @@ public static void createDebug(final @NotNull LevelledMobs main, final CommandSe
try{
Files.writeString(serverInfoFile.toPath(), generateSystemInfo(main), StandardCharsets.UTF_8);
}
- catch (IOException e){
+ catch (final IOException e){
e.printStackTrace();
}
@@ -43,7 +43,7 @@ public static void createDebug(final @NotNull LevelledMobs main, final CommandSe
fos = new FileOutputStream(zipFile);
zipOut = new ZipOutputStream(fos);
- for (String srcFile : srcFiles) {
+ for (final String srcFile : srcFiles) {
final File fileToZip = srcFile.contains(File.separator) ?
new File(srcFile) : new File(pluginDir, srcFile);
@@ -61,7 +61,7 @@ public static void createDebug(final @NotNull LevelledMobs main, final CommandSe
result = true;
}
- catch (IOException e){
+ catch (final IOException e){
e.printStackTrace();
}
finally {
@@ -70,11 +70,12 @@ public static void createDebug(final @NotNull LevelledMobs main, final CommandSe
if (fis != null) fis.close();
if (fos != null) fos.close();
}
- catch (Exception ignored) {}
+ catch (final Exception ignored) {}
}
final File serverInfo = new File(pluginDir, "serverinfo.txt");
- if (serverInfo.exists()) serverInfo.delete();
+ if (serverInfo.exists()) //noinspection ResultOfMethodCallIgnored
+ serverInfo.delete();
if (result)
sender.sendMessage("Created file: " + zipFile.getAbsolutePath());
@@ -92,7 +93,7 @@ private static String generateSystemInfo(final @NotNull LevelledMobs main){
try{
shaDigest = MessageDigest.getInstance("SHA-256");
}
- catch (Exception ignored) {}
+ catch (final Exception ignored) {}
sb.append(main.getDescription().getName());
sb.append(" ");
@@ -148,19 +149,18 @@ private static String generateSystemInfo(final @NotNull LevelledMobs main){
}
@Nullable
- private static String getFileChecksum(final MessageDigest digest, final File file)
- {
+ private static String getFileChecksum(final MessageDigest digest, final File file) {
// taken from https://howtodoinjava.com/java/io/sha-md5-file-checksum-hash/
final byte[] byteArray = new byte[1024];
int bytesCount;
- try (FileInputStream fis = new FileInputStream(file)){
+ try (final FileInputStream fis = new FileInputStream(file)){
while ((bytesCount = fis.read(byteArray)) != -1) {
digest.update(byteArray, 0, bytesCount);
}
}
- catch (IOException e) {
+ catch (final IOException e) {
e.printStackTrace();
return null;
}
@@ -168,7 +168,7 @@ private static String getFileChecksum(final MessageDigest digest, final File fil
final byte[] bytes = digest.digest();
final StringBuilder sb = new StringBuilder();
- for (byte aByte : bytes) sb.append(Integer.toString((aByte & 0xff) + 0x100, 16).substring(1));
+ for (final byte aByte : bytes) sb.append(Integer.toString((aByte & 0xff) + 0x100, 16).substring(1));
return sb.toString();
}
diff --git a/src/main/java/me/lokka30/levelledmobs/misc/DebugType.java b/src/main/java/me/lokka30/levelledmobs/misc/DebugType.java
index c11c75001..26f6ff894 100644
--- a/src/main/java/me/lokka30/levelledmobs/misc/DebugType.java
+++ b/src/main/java/me/lokka30/levelledmobs/misc/DebugType.java
@@ -131,5 +131,9 @@ public enum DebugType {
DENIED_RULE_PERMISSION,
- ATTRIBUTE_MULTIPLIERS
+ ATTRIBUTE_MULTIPLIERS,
+
+ CUSTOM_DROPS,
+
+ THREAD_LOCKS
}
diff --git a/src/main/java/me/lokka30/levelledmobs/misc/FileLoader.java b/src/main/java/me/lokka30/levelledmobs/misc/FileLoader.java
index 37d260c68..01bb17f7c 100644
--- a/src/main/java/me/lokka30/levelledmobs/misc/FileLoader.java
+++ b/src/main/java/me/lokka30/levelledmobs/misc/FileLoader.java
@@ -23,7 +23,7 @@
public final class FileLoader {
public static final int SETTINGS_FILE_VERSION = 32; // Last changed: v3.1.5 b503
- public static final int MESSAGES_FILE_VERSION = 6; // Last changed: v3.1.2 b485
+ public static final int MESSAGES_FILE_VERSION = 7; // Last changed: v3.3.0 b567
public static final int CUSTOMDROPS_FILE_VERSION = 10; // Last changed: v3.1.0 b474
public static final int RULES_FILE_VERSION = 2; // Last changed: v3.2.0 b529
@@ -40,9 +40,9 @@ public static YamlConfiguration loadFile(@NotNull final Plugin plugin, String cf
final File file = new File(plugin.getDataFolder(), cfgName);
saveResourceIfNotExists(plugin, file);
- try (FileInputStream fs = new FileInputStream(file)) {
+ try (final FileInputStream fs = new FileInputStream(file)) {
new Yaml().load(fs);
- } catch (Exception e) {
+ } catch (final Exception e) {
Utils.logger.error("&4Error reading " + cfgName + ". " + e.getMessage());
return null;
}
@@ -73,7 +73,7 @@ public static YamlConfiguration loadFile(@NotNull final Plugin plugin, String cf
else if (!isRules)
FileMigrator.copyYmlValues(backedupFile, file, fileVersion);
else
- FileMigrator.migrateRules(backedupFile, file, fileVersion);
+ FileMigrator.migrateRules(file);
// reload cfg from the updated values
cfg = YamlConfiguration.loadConfiguration(file);
@@ -91,13 +91,6 @@ public static void saveResourceIfNotExists(final Plugin instance, @NotNull final
}
}
- public static void saveResourceIfNotExists(final Plugin instance, @NotNull final File file, final String filename) {
- if (!file.exists()) {
- Utils.logger.info("&fFile Loader: &7File '&b" + file.getName() + "&7' doesn't exist, creating it now...");
- instance.saveResource(filename, false);
- }
- }
-
private static void checkFileVersion(final File file, final int compatibleVersion, final int installedVersion) {
if (compatibleVersion == installedVersion)
return;
diff --git a/src/main/java/me/lokka30/levelledmobs/misc/FileMigrator.java b/src/main/java/me/lokka30/levelledmobs/misc/FileMigrator.java
index 62b58bc5e..542ce6afc 100644
--- a/src/main/java/me/lokka30/levelledmobs/misc/FileMigrator.java
+++ b/src/main/java/me/lokka30/levelledmobs/misc/FileMigrator.java
@@ -28,7 +28,7 @@
*/
public class FileMigrator {
- private static int getFieldDepth(@NotNull String line) {
+ private static int getFieldDepth(@NotNull final String line) {
int whiteSpace = 0;
for (int i = 0; i < line.length(); i++) {
@@ -39,27 +39,27 @@ private static int getFieldDepth(@NotNull String line) {
}
private static class FieldInfo {
- public String simpleValue;
- public List valueList;
- public final int depth;
- public boolean hasValue;
+ String simpleValue;
+ List valueList;
+ final int depth;
+ boolean hasValue;
- public FieldInfo(final String value, int depth) {
+ FieldInfo(final String value, final int depth) {
this.simpleValue = value;
this.depth = depth;
}
- public FieldInfo(final String value, final int depth, final boolean isListValue) {
+ FieldInfo(final String value, final int depth, final boolean isListValue) {
if (isListValue) addListValue(value);
else this.simpleValue = value;
this.depth = depth;
}
- public boolean isList(){
+ boolean isList(){
return valueList != null;
}
- public void addListValue(final String value){
+ void addListValue(final String value){
if (valueList == null) valueList = new LinkedList<>();
valueList.add(value);
}
@@ -80,15 +80,15 @@ public String toString() {
}
private static class KeySectionInfo{
- public KeySectionInfo(){
+ KeySectionInfo(){
this.lines = new LinkedList<>();
}
- public int lineNumber;
+ int lineNumber;
@Nonnull
- final public List lines;
- public int sectionNumber;
- public int sectionStartingLine;
+ final List lines;
+ int sectionNumber;
+ int sectionStartingLine;
}
private static String getKeyFromList(final @NotNull List list, final String currentKey){
@@ -144,7 +144,7 @@ public static void migrateSettingsToRules(@NotNull final LevelledMobs main){
final String msg2 = Utils.colorizeAllInList(msg).toString();
Utils.logger.warning(msg2.substring(1, msg2.length() - 2));
main.migratedFromPre30 = true;
- } catch (IOException e) {
+ } catch (final IOException e) {
e.printStackTrace();
}
@@ -165,8 +165,8 @@ private static String compileListFromArray(final @NotNull List list){
return sb.toString();
}
- protected static void copyCustomDrops(@NotNull final File from, @NotNull final File to, final int fileVersion){
- TreeMap