diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fc4ca94
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+.gradle
+.idea
+build
+target
diff --git a/BattlePass.iml b/BattlePass.iml
new file mode 100644
index 0000000..a589521
--- /dev/null
+++ b/BattlePass.iml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ SPIGOT
+
+ 1
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/Lino/battlePass/BattlePass.java b/src/main/java/com/Lino/battlePass/BattlePass.java
index 908f4e3..2bd08a7 100644
--- a/src/main/java/com/Lino/battlePass/BattlePass.java
+++ b/src/main/java/com/Lino/battlePass/BattlePass.java
@@ -92,6 +92,8 @@ public void run() {
coinsDistributionTask = new CoinsDistributionTask(BattlePass.this);
if (nextDist != null) {
coinsDistributionTask.setNextDistribution(nextDist);
+ } else {
+ coinsDistributionTask.resetDistributionTime();
}
coinsDistributionTask.runTaskTimer(BattlePass.this, 200L, 1200L);
});
@@ -99,7 +101,7 @@ public void run() {
registerPlaceholders();
checkForUpdates();
- getLogger().info(messageManager.getMessage("messages.plugin-enabled"));
+ getLogger().info("✓ Battle Pass enabled successfully!");
this.cancel();
} else if (attempts >= MAX_ATTEMPTS) {
getLogger().severe("Failed to initialize MissionManager after 30 seconds!");
@@ -216,7 +218,7 @@ public void reload() {
boolean isBattlePassGUI = false;
int currentPage = 1;
- for (int i = 1; i <= 6; i++) {
+ for (int i = 1; i <= rewardManager.getMaxPage(); i++) {
if (title.equals(messageManager.getMessage("gui.battlepass", "%page%", String.valueOf(i)))) {
isBattlePassGUI = true;
currentPage = i;
diff --git a/src/main/java/com/Lino/battlePass/commands/BattlePassCommand.java b/src/main/java/com/Lino/battlePass/commands/BattlePassCommand.java
index ce0e7c0..aac597b 100644
--- a/src/main/java/com/Lino/battlePass/commands/BattlePassCommand.java
+++ b/src/main/java/com/Lino/battlePass/commands/BattlePassCommand.java
@@ -266,7 +266,7 @@ private boolean handleXPCommand(CommandSender sender, String[] args, boolean add
totalXP = Math.max(0, totalXP - amount);
int newLevel = 1;
- while (totalXP >= xpPerLevel && newLevel < 54) {
+ while (totalXP >= xpPerLevel && newLevel < plugin.getRewardManager().getMaxLevel()) {
totalXP -= xpPerLevel;
newLevel++;
}
@@ -480,7 +480,7 @@ private boolean handleGiveItemCommand(CommandSender sender, String[] args) {
private void checkLevelUp(Player player, PlayerData data, int xpPerLevel) {
boolean leveled = false;
- while (data.xp >= xpPerLevel && data.level < 54) {
+ while (data.xp >= xpPerLevel && data.level < plugin.getRewardManager().getMaxLevel()) {
data.xp -= xpPerLevel;
data.level++;
data.totalLevels++;
@@ -491,7 +491,7 @@ private void checkLevelUp(Player player, PlayerData data, int xpPerLevel) {
"%level%", String.valueOf(data.level)));
player.playSound(player.getLocation(), Sound.UI_TOAST_CHALLENGE_COMPLETE, 1.0f, 1.0f);
- int available = plugin.getRewardManager().countAvailableRewards(player, data);
+ int available = plugin.getRewardManager().countAvailableRewards(data);
if (available > 0) {
player.sendMessage(plugin.getMessageManager().getPrefix() +
plugin.getMessageManager().getMessage("messages.new-rewards"));
diff --git a/src/main/java/com/Lino/battlePass/gui/BattlePassGui.java b/src/main/java/com/Lino/battlePass/gui/BattlePassGui.java
index 499a761..650a7c7 100644
--- a/src/main/java/com/Lino/battlePass/gui/BattlePassGui.java
+++ b/src/main/java/com/Lino/battlePass/gui/BattlePassGui.java
@@ -56,6 +56,7 @@ private void setupProgressItem(Inventory gui) {
.replace("%level%", String.valueOf(playerData.level))
.replace("%xp%", String.valueOf(playerData.xp))
.replace("%xp_needed%", String.valueOf(plugin.getConfigManager().getXpPerLevel()))
+ .replace("%max_level%", String.valueOf(maxLevel))
.replace("%premium_status%", premiumStatus)
.replace("%season_time%", plugin.getMissionManager().getTimeUntilSeasonEnd());
lore.add(GradientColorParser.parse(processedLine));
@@ -209,8 +210,7 @@ private void setupNavigationButtons(Inventory gui) {
gui.setItem(45, createNavigationItem(false, page - 1));
}
- int maxPages = (int) Math.ceil(maxLevel / 9.0);
- if (page < maxPages) {
+ if (page < plugin.getRewardManager().getMaxPage()) {
gui.setItem(53, createNavigationItem(true, page + 1));
}
}
diff --git a/src/main/java/com/Lino/battlePass/gui/RewardsEditorGui.java b/src/main/java/com/Lino/battlePass/gui/RewardsEditorGui.java
index 781d55b..e3c2020 100644
--- a/src/main/java/com/Lino/battlePass/gui/RewardsEditorGui.java
+++ b/src/main/java/com/Lino/battlePass/gui/RewardsEditorGui.java
@@ -28,6 +28,7 @@ public void open() {
}
Inventory gui = createInventory();
+ String maxLevel = String.valueOf(plugin.getRewardManager().getMaxLevel());
ItemStack freeRewards = new ItemStack(Material.CHEST);
ItemMeta freeMeta = freeRewards.getItemMeta();
@@ -39,7 +40,7 @@ public void open() {
freeLore.add(GradientColorParser.parse("&7that all players can claim"));
freeLore.add("");
freeLore.add(GradientColorParser.parse("▼ Features ▼"));
- freeLore.add(GradientColorParser.parse("&7• View all 54 levels"));
+ freeLore.add(GradientColorParser.parse("&7• View all %max_level% levels".replace("%max_level%", maxLevel)));
freeLore.add(GradientColorParser.parse("&7• Add/remove items"));
freeLore.add(GradientColorParser.parse("&7• Configure commands"));
freeLore.add("");
@@ -59,7 +60,7 @@ public void open() {
premiumLore.add(GradientColorParser.parse("&7exclusive to premium pass holders"));
premiumLore.add("");
premiumLore.add(GradientColorParser.parse("▼ Features ▼"));
- premiumLore.add(GradientColorParser.parse("&7• View all 54 levels"));
+ premiumLore.add(GradientColorParser.parse("&7• View all %max_level% levels".replace("%max_level%", maxLevel)));
premiumLore.add(GradientColorParser.parse("&7• Add/remove items"));
premiumLore.add(GradientColorParser.parse("&7• Configure commands"));
premiumLore.add("");
diff --git a/src/main/java/com/Lino/battlePass/listeners/CustomItemsListener.java b/src/main/java/com/Lino/battlePass/listeners/CustomItemsListener.java
index cefaabc..c9e0303 100644
--- a/src/main/java/com/Lino/battlePass/listeners/CustomItemsListener.java
+++ b/src/main/java/com/Lino/battlePass/listeners/CustomItemsListener.java
@@ -171,7 +171,7 @@ private void handleLevelBoostUse(PlayerInteractEvent event, Player player) {
}
if (levelsGained > 0) {
- int available = plugin.getRewardManager().countAvailableRewards(player, data);
+ int available = plugin.getRewardManager().countAvailableRewards(data);
if (available > 0) {
player.sendMessage(plugin.getMessageManager().getPrefix() +
plugin.getMessageManager().getMessage("messages.new-rewards"));
diff --git a/src/main/java/com/Lino/battlePass/listeners/GuiClickListener.java b/src/main/java/com/Lino/battlePass/listeners/GuiClickListener.java
index 5113c40..a7442d1 100644
--- a/src/main/java/com/Lino/battlePass/listeners/GuiClickListener.java
+++ b/src/main/java/com/Lino/battlePass/listeners/GuiClickListener.java
@@ -85,8 +85,7 @@ private void handleBattlePassClick(Player player, ItemStack clicked, int slot) {
String action = meta.getPersistentDataContainer().get(plugin.getEventManager().getNavigationKey(), PersistentDataType.STRING);
// Calcolo dinamico delle pagine massime
- int maxLevel = plugin.getRewardManager().getMaxLevel();
- int maxPages = (int) Math.ceil(maxLevel / 9.0);
+ int maxPages = plugin.getRewardManager().getMaxPage();
if (maxPages < 1) maxPages = 1;
if ("previous".equals(action) && currentPage > 1) {
@@ -197,21 +196,19 @@ private void handleDailyRewardClaim(Player player, int currentPage) {
data.lastDailyReward = now;
int xpPerLevel = plugin.getConfigManager().getXpPerLevel();
- boolean leveled = false;
int maxLevel = plugin.getRewardManager().getMaxLevel();
while (data.xp >= xpPerLevel && data.level < maxLevel) {
data.xp -= xpPerLevel;
data.level++;
data.totalLevels++;
- leveled = true;
player.sendMessage(plugin.getMessageManager().getPrefix() +
plugin.getMessageManager().getMessage("messages.level-up",
"%level%", String.valueOf(data.level)));
player.playSound(player.getLocation(), Sound.UI_TOAST_CHALLENGE_COMPLETE, 1.0f, 1.0f);
- int available = plugin.getRewardManager().countAvailableRewards(player, data);
+ int available = plugin.getRewardManager().countAvailableRewards(data);
if (available > 0) {
player.sendMessage(plugin.getMessageManager().getPrefix() +
plugin.getMessageManager().getMessage("messages.new-rewards"));
diff --git a/src/main/java/com/Lino/battlePass/listeners/MissionEditorListener.java b/src/main/java/com/Lino/battlePass/listeners/MissionEditorListener.java
index d2490ed..46b44c9 100644
--- a/src/main/java/com/Lino/battlePass/listeners/MissionEditorListener.java
+++ b/src/main/java/com/Lino/battlePass/listeners/MissionEditorListener.java
@@ -123,7 +123,7 @@ private void handleDetailsClick(Player player, InventoryClickEvent event, String
if (slot == 12) {
ConfigurationSection section = plugin.getConfigManager().getMissionsConfig().getConfigurationSection("mission-pools." + key);
if (section != null) {
- String missionType = section.getString("type");
+ String missionType = section.getString("type", "UNKNOWN");
isTargetRequired = plugin.getMissionEditorManager().isTargetRequired(missionType);
}
}
diff --git a/src/main/java/com/Lino/battlePass/listeners/MissionProgressListener.java b/src/main/java/com/Lino/battlePass/listeners/MissionProgressListener.java
index 137c4be..0a4ef23 100644
--- a/src/main/java/com/Lino/battlePass/listeners/MissionProgressListener.java
+++ b/src/main/java/com/Lino/battlePass/listeners/MissionProgressListener.java
@@ -4,8 +4,7 @@
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
-import org.bukkit.entity.EntityType;
-import org.bukkit.entity.Player;
+import org.bukkit.entity.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
@@ -15,9 +14,13 @@
import org.bukkit.event.entity.*;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.inventory.FurnaceExtractEvent;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.*;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.projectiles.ProjectileSource;
+import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@@ -25,6 +28,7 @@ public class MissionProgressListener implements Listener {
private final BattlePass plugin;
private final Map lastLocations = new ConcurrentHashMap<>();
+ private final Map distanceBuffer = new ConcurrentHashMap<>();
private final Set oreTypes = EnumSet.noneOf(Material.class);
private final Map> recentlyPlacedBlocks = new ConcurrentHashMap<>();
@@ -36,7 +40,7 @@ public MissionProgressListener(BattlePass plugin) {
private void initializeOreTypes() {
for (Material mat : Material.values()) {
String name = mat.name();
- if (name.endsWith("_ORE") || name.equals("ANCIENT_DEBRIS") || name.equals("NETHER_QUARTZ_ORE") || name.equals("GILDED_BLACKSTONE")) {
+ if (name.endsWith("_ORE") || name.equals("ANCIENT_DEBRIS") || name.equals("GILDED_BLACKSTONE")) {
oreTypes.add(mat);
}
}
@@ -69,9 +73,12 @@ public void onPlayerTeleport(PlayerTeleportEvent event) {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerMove(PlayerMoveEvent event) {
- if (event.getFrom().getBlockX() == event.getTo().getBlockX() &&
- event.getFrom().getBlockY() == event.getTo().getBlockY() &&
- event.getFrom().getBlockZ() == event.getTo().getBlockZ()) {
+ Location from = event.getFrom();
+ Location to = event.getTo();
+
+ if (from.getBlockX() == to.getBlockX()
+ && from.getBlockY() == to.getBlockY()
+ && from.getBlockZ() == to.getBlockZ()) {
return;
}
@@ -79,50 +86,90 @@ public void onPlayerMove(PlayerMoveEvent event) {
UUID uuid = player.getUniqueId();
Location last = lastLocations.get(uuid);
- Location toLoc = event.getTo();
+ if (last == null) {
+ lastLocations.put(uuid, to);
+ return;
+ }
+
+ if (last.getWorld() == null || to.getWorld() == null
+ || !last.getWorld().getName().equals(to.getWorld().getName())) {
+ lastLocations.put(uuid, to);
+ distanceBuffer.remove(uuid);
+ return;
+ }
+
+ double distance;
+ try {
+ distance = last.distance(to);
+ } catch (IllegalArgumentException e) {
+ lastLocations.put(uuid, to);
+ distanceBuffer.remove(uuid);
+ return;
+ }
+
+ if (distance > 0 && distance < 100) {
- if (last != null) {
- if (last.getWorld() == null || toLoc.getWorld() == null ||
- !last.getWorld().getName().equals(toLoc.getWorld().getName())) {
- lastLocations.put(uuid, toLoc);
- return;
+ String mode;
+ if (player.isFlying() || player.isGliding()) {
+ mode = "FLY";
+ } else if (player.isSwimming() || player.getLocation().getBlock().isLiquid()) {
+ mode = "SWIM";
+ } else if (player.isSneaking()) {
+ mode = "SNEAK";
+ } else {
+ mode = "WALK";
}
- try {
- double distance = last.distance(toLoc);
- if (distance >= 1 && distance < 100) {
- plugin.getMissionManager().progressMission(player, "WALK_DISTANCE", "ANY", (int) distance);
- }
- } catch (IllegalArgumentException e) {
+ double buf = distanceBuffer.getOrDefault(uuid, 0.0);
+ buf += distance;
+ int whole = (int) buf;
+ if (whole > 0) {
+ plugin.getMissionManager().progressMission(player, "WALK_DISTANCE", mode, whole);
+ buf -= whole;
}
- lastLocations.put(uuid, toLoc);
- } else {
- lastLocations.put(uuid, toLoc);
+ distanceBuffer.put(uuid, buf);
}
+
+ lastLocations.put(uuid, to);
}
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerDeath(PlayerDeathEvent event) {
- plugin.getMissionManager().progressMission(event.getEntity(), "DEATH", "ANY", 1);
+ Player player = event.getEntity();
+ EntityDamageEvent last = player.getLastDamageCause();
+ if (last == null) {
+ plugin.getMissionManager().progressMission(player, "DEATH", "UNKNOWN", 1);
+ return;
+ }
+
+ for (String type : enumerateDamageTypes(last)) {
+ plugin.getMissionManager().progressMission(player, "DEATH", type, 1);
+ }
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
- public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
- if (event.getDamager() instanceof Player) {
- Player player = (Player) event.getDamager();
- plugin.getMissionManager().progressMission(player, "DAMAGE_DEALT", "ANY", (int) event.getDamage());
+ public void onEntityDamage(EntityDamageEvent event) {
+ if (!(event.getEntity() instanceof Player player)) return;
+ int amount = (int) event.getFinalDamage();
+
+ for (String type : enumerateDamageTypes(event)) {
+ plugin.getMissionManager().progressMission(player, "DAMAGE_TAKEN", type, amount);
}
+ }
- if (event.getEntity() instanceof Player) {
- Player player = (Player) event.getEntity();
- plugin.getMissionManager().progressMission(player, "DAMAGE_TAKEN", "ANY", (int) event.getDamage());
+ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+ public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
+ Entity trueDamager = getTrueDamager(event.getDamager());
+ if (trueDamager instanceof Player player) {
+ int amount = (int) Math.round(event.getFinalDamage());
+ String victimType = safeName(event.getEntity().getType().name());
+ plugin.getMissionManager().progressMission(player, "DAMAGE_DEALT", victimType, amount);
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onEntityBreed(EntityBreedEvent event) {
- if (event.getBreeder() instanceof Player) {
- Player player = (Player) event.getBreeder();
+ if (event.getBreeder() instanceof Player player) {
String entityType = event.getEntity().getType().name();
plugin.getMissionManager().progressMission(player, "BREED_ANIMAL", entityType, 1);
}
@@ -130,32 +177,42 @@ public void onEntityBreed(EntityBreedEvent event) {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onEntityTame(EntityTameEvent event) {
- if (event.getOwner() instanceof Player) {
- Player player = (Player) event.getOwner();
+ if (event.getOwner() instanceof Player player) {
String entityType = event.getEntity().getType().name();
plugin.getMissionManager().progressMission(player, "TAME_ANIMAL", entityType, 1);
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
- public void onVillagerTrade(PlayerInteractEntityEvent event) {
- if (event.getRightClicked().getType() == EntityType.VILLAGER) {
- Player player = event.getPlayer();
- plugin.getMissionManager().progressMission(player, "TRADE_VILLAGER", "ANY", 1);
+ public void onVillagerTrade(InventoryClickEvent event) {
+ if (!(event.getWhoClicked() instanceof Player player)) return;
+ if (event.getSlotType() != InventoryType.SlotType.RESULT) return;
+ if (event.getCurrentItem() == null || event.getCurrentItem().getType() == Material.AIR) return;
+
+ if (event.getInventory().getHolder() instanceof Villager villager) {
+ String profession = getProfessionName(villager);
+ if (profession.equals("NONE")) profession = "VILLAGER";
+
+ plugin.getMissionManager().progressMission(player, "TRADE_VILLAGER", profession, 1);
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onEnchantItem(EnchantItemEvent event) {
- plugin.getMissionManager().progressMission(event.getEnchanter(), "ENCHANT_ITEM", "ANY", 1);
+ Player player = event.getEnchanter();
+ ItemStack item = event.getItem();
+
+ if (item.getType() != Material.AIR) {
+ String itemType = item.getType().name();
+ plugin.getMissionManager().progressMission(player, "ENCHANT_ITEM", itemType, 1);
+ }
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerFish(PlayerFishEvent event) {
if (event.getState() == PlayerFishEvent.State.CAUGHT_FISH && event.getCaught() != null) {
Player player = event.getPlayer();
- if (event.getCaught() instanceof org.bukkit.entity.Item) {
- org.bukkit.entity.Item item = (org.bukkit.entity.Item) event.getCaught();
+ if (event.getCaught() instanceof org.bukkit.entity.Item item) {
String itemType = item.getItemStack().getType().name();
plugin.getMissionManager().progressMission(player, "FISH_ITEM", itemType, 1);
}
@@ -164,9 +221,8 @@ public void onPlayerFish(PlayerFishEvent event) {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onCraftItem(CraftItemEvent event) {
- if (!(event.getWhoClicked() instanceof Player)) return;
+ if (!(event.getWhoClicked() instanceof Player player)) return;
- Player player = (Player) event.getWhoClicked();
ItemStack result = event.getRecipe().getResult();
if (result == null || result.getType() == Material.AIR) return;
@@ -200,11 +256,7 @@ public void onBlockPlace(BlockPlaceEvent event) {
Location blockLoc = event.getBlock().getLocation();
UUID uuid = player.getUniqueId();
- Map playerPlacedBlocks = recentlyPlacedBlocks.get(uuid);
- if (playerPlacedBlocks == null) {
- playerPlacedBlocks = new HashMap<>();
- recentlyPlacedBlocks.put(uuid, playerPlacedBlocks);
- }
+ Map playerPlacedBlocks = recentlyPlacedBlocks.computeIfAbsent(uuid, k -> new HashMap<>());
Long lastPlaced = playerPlacedBlocks.get(blockLoc);
long currentTime = System.currentTimeMillis();
@@ -277,6 +329,89 @@ public void onPlayerShearEntity(PlayerShearEntityEvent event) {
}
}
+ public String getProfessionName(Villager villager) {
+ Villager.Profession profession = villager.getProfession();
+
+ try {
+ // Old method
+ return profession.name();
+ } catch (Exception e) {
+ // New method ('name()' is deprecated since version 1.21 and marked for removal)
+ // profession.key().value().replace("minecraft:", "").toUpperCase();
+ try {
+ Method keyMethod = profession.getClass().getMethod("key");
+ Object namespacedKey = keyMethod.invoke(profession);
+ Method valueMethod = namespacedKey.getClass().getMethod("value");
+ String keyValue = (String) valueMethod.invoke(namespacedKey);
+ return keyValue.replace("minecraft:", "").toUpperCase();
+ } catch (Exception ex) {
+ return "UNKNOWN";
+ }
+ }
+ }
+
+ private List enumerateDamageTypes(EntityDamageEvent event) {
+ List result = new ArrayList<>();
+
+ if (event instanceof EntityDamageByEntityEvent edbe) {
+ Entity rawDamager = edbe.getDamager();
+
+ if (rawDamager instanceof Projectile projectile) {
+ result.add(safeName(projectile.getType().name()));
+
+ ProjectileSource shooter = projectile.getShooter();
+ if (shooter instanceof Entity shooterEntity) {
+ if (shooterEntity instanceof Player) {
+ result.add("PLAYER");
+ } else if (shooterEntity instanceof LivingEntity livingShooter) {
+ String mobBase = safeName(livingShooter.getType().name());
+ result.add(mobBase);
+ } else {
+ result.add(safeName(shooterEntity.getType().name()));
+ }
+ }
+ } else {
+ if (rawDamager instanceof Player) {
+ result.add("PLAYER");
+ } else if (rawDamager instanceof LivingEntity living) {
+ result.add(safeName(living.getType().name()));
+ } else {
+ result.add(safeName(rawDamager.getType().name()));
+ }
+ }
+ }
+
+ result.add(safeName(getCauseName(event.getCause())));
+
+ return new ArrayList<>(new LinkedHashSet<>(result));
+ }
+
+ private Entity getTrueDamager(Entity damager) {
+ if (damager instanceof Projectile projectile) {
+ ProjectileSource ps = projectile.getShooter();
+ if (ps instanceof Entity shooterEntity) return shooterEntity;
+ }
+ return damager;
+ }
+
+ private String getCauseName(EntityDamageEvent.DamageCause cause) {
+ switch (cause) {
+ case FIRE, FIRE_TICK -> {
+ return "FIRE";
+ }
+ case BLOCK_EXPLOSION, ENTITY_EXPLOSION -> {
+ return "EXPLOSION";
+ }
+ default -> {
+ return cause.name();
+ }
+ }
+ }
+
+ private String safeName(String s) {
+ return s == null ? "UNKNOWN" : s.replaceAll("[^A-Z0-9_]", "_").toUpperCase();
+ }
+
public void initializePlayerLocation(UUID uuid, Location location) {
lastLocations.put(uuid, location);
recentlyPlacedBlocks.put(uuid, new HashMap<>());
@@ -284,6 +419,7 @@ public void initializePlayerLocation(UUID uuid, Location location) {
public void cleanupPlayer(UUID uuid) {
lastLocations.remove(uuid);
+ distanceBuffer.remove(uuid);
recentlyPlacedBlocks.remove(uuid);
}
}
\ No newline at end of file
diff --git a/src/main/java/com/Lino/battlePass/listeners/PlayerConnectionListener.java b/src/main/java/com/Lino/battlePass/listeners/PlayerConnectionListener.java
index 2dd55aa..933ae7f 100644
--- a/src/main/java/com/Lino/battlePass/listeners/PlayerConnectionListener.java
+++ b/src/main/java/com/Lino/battlePass/listeners/PlayerConnectionListener.java
@@ -11,7 +11,6 @@
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.scheduler.BukkitRunnable;
-import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@@ -45,7 +44,7 @@ public void run() {
PlayerData data = plugin.getPlayerDataManager().getPlayerData(uuid);
if (data != null) {
- int available = plugin.getRewardManager().countAvailableRewards(player, data);
+ int available = plugin.getRewardManager().countAvailableRewards(data);
if (available > 0) {
player.sendMessage(plugin.getMessageManager().getPrefix() +
plugin.getMessageManager().getMessage("messages.rewards-available",
diff --git a/src/main/java/com/Lino/battlePass/managers/DatabaseManager.java b/src/main/java/com/Lino/battlePass/managers/DatabaseManager.java
index 318231b..2b5ba55 100644
--- a/src/main/java/com/Lino/battlePass/managers/DatabaseManager.java
+++ b/src/main/java/com/Lino/battlePass/managers/DatabaseManager.java
@@ -170,13 +170,22 @@ private void createTables() throws SQLException {
"name TEXT," +
"type TEXT," +
"target TEXT," +
+ "additional_targets TEXT," +
"required INTEGER," +
"xp_reward INTEGER," +
"date TEXT)"
);
if (!isMySQL) {
- stmt.executeUpdate("CREATE INDEX IF NOT EXISTS idx_missions_uuid_date ON " + prefix + "missions(uuid, date)");
+ try {
+ stmt.executeUpdate("ALTER TABLE " + prefix + "daily_missions ADD COLUMN additional_targets TEXT");
+ } catch (SQLException ignored) {
+ }
+ } else {
+ try {
+ stmt.executeUpdate("ALTER TABLE " + prefix + "daily_missions ADD COLUMN additional_targets TEXT DEFAULT ''");
+ } catch (SQLException ignored) {
+ }
}
}
} finally {
@@ -567,8 +576,8 @@ public CompletableFuture saveDailyMissions(List missions, String
if (missions.isEmpty()) return;
String insertSql = isMySQL
- ? "INSERT INTO " + prefix + "daily_missions (name, type, target, required, xp_reward, date) VALUES (?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE name=VALUES(name)"
- : "INSERT OR REPLACE INTO " + prefix + "daily_missions (name, type, target, required, xp_reward, date) VALUES (?, ?, ?, ?, ?, ?)";
+ ? "INSERT INTO " + prefix + "daily_missions (name, type, target, additional_targets, required, xp_reward, date) VALUES (?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE name=VALUES(name), type=VALUES(type), target=VALUES(target), additional_targets=VALUES(additional_targets), required=VALUES(required), xp_reward=VALUES(xp_reward)"
+ : "INSERT OR REPLACE INTO " + prefix + "daily_missions (name, type, target, additional_targets, required, xp_reward, date) VALUES (?, ?, ?, ?, ?, ?, ?)";
Connection conn = null;
boolean shouldClose = isMySQL;
@@ -584,9 +593,10 @@ public CompletableFuture saveDailyMissions(List missions, String
ps.setString(1, mission.name);
ps.setString(2, mission.type);
ps.setString(3, mission.target);
- ps.setInt(4, mission.required);
- ps.setInt(5, mission.xpReward);
- ps.setString(6, missionDate);
+ ps.setString(4, String.join(",", mission.additionalTargets));
+ ps.setInt(5, mission.required);
+ ps.setInt(6, mission.xpReward);
+ ps.setString(7, missionDate);
ps.addBatch();
}
ps.executeBatch();
@@ -616,10 +626,17 @@ public CompletableFuture> loadDailyMissions() {
ps.setString(1, missionDate);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
+ String additionalTargetsStr = rs.getString("additional_targets");
+ List additionalTargets = new ArrayList<>();
+ if (additionalTargetsStr != null && !additionalTargetsStr.isEmpty()) {
+ additionalTargets = Arrays.asList(additionalTargetsStr.split(","));
+ }
+
loadedMissions.add(new Mission(
rs.getString("name"),
rs.getString("type"),
rs.getString("target"),
+ additionalTargets,
rs.getInt("required"),
rs.getInt("xp_reward")
));
diff --git a/src/main/java/com/Lino/battlePass/managers/GuiManager.java b/src/main/java/com/Lino/battlePass/managers/GuiManager.java
index bfeebfd..493efd4 100644
--- a/src/main/java/com/Lino/battlePass/managers/GuiManager.java
+++ b/src/main/java/com/Lino/battlePass/managers/GuiManager.java
@@ -31,8 +31,7 @@ public GuiManager(BattlePass plugin, PlayerDataManager playerDataManager, Missio
public void openBattlePassGUI(Player player, int page) {
if (page < 1) page = 1;
- int maxLevel = rewardManager.getMaxLevel();
- int maxPages = (int) Math.ceil(maxLevel / 9.0);
+ int maxPages = plugin.getRewardManager().getMaxPage();
if (maxPages < 1) maxPages = 1;
if (page > maxPages) page = maxPages;
diff --git a/src/main/java/com/Lino/battlePass/managers/MissionEditorManager.java b/src/main/java/com/Lino/battlePass/managers/MissionEditorManager.java
index 9d8aa50..0118a2c 100644
--- a/src/main/java/com/Lino/battlePass/managers/MissionEditorManager.java
+++ b/src/main/java/com/Lino/battlePass/managers/MissionEditorManager.java
@@ -203,19 +203,10 @@ private String getDefaultTarget(String type) {
}
public boolean isTargetRequired(String type) {
- switch (type) {
- case "WALK_DISTANCE":
- case "PLAY_TIME":
- case "GAIN_XP":
- case "DAMAGE_DEALT":
- case "DAMAGE_TAKEN":
- case "DEATH":
- case "TRADE_VILLAGER":
- case "ENCHANT_ITEM":
- return false;
- default:
- return true;
- }
+ return switch (type) {
+ case "PLAY_TIME", "GAIN_XP" -> false;
+ default -> true;
+ };
}
public boolean isEditing(UUID uuid) {
diff --git a/src/main/java/com/Lino/battlePass/managers/MissionGenerator.java b/src/main/java/com/Lino/battlePass/managers/MissionGenerator.java
index d01eeb2..8f9eb0a 100644
--- a/src/main/java/com/Lino/battlePass/managers/MissionGenerator.java
+++ b/src/main/java/com/Lino/battlePass/managers/MissionGenerator.java
@@ -3,7 +3,6 @@
import com.Lino.battlePass.models.Mission;
import com.Lino.battlePass.models.MissionTemplate;
import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.configuration.file.FileConfiguration;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
@@ -16,7 +15,7 @@ public MissionGenerator(ConfigManager configManager) {
this.configManager = configManager;
}
- public List generateDailyMissions(String missionDate) {
+ public List generateDailyMissions() {
ConfigurationSection pools = configManager.getMissionsConfig().getConfigurationSection("mission-pools");
if (pools == null) {
return new ArrayList<>();
@@ -24,7 +23,6 @@ public List generateDailyMissions(String missionDate) {
List newMissions = new ArrayList<>();
List weightedTemplates = new ArrayList<>();
- Map uniqueTemplates = new HashMap<>();
for (String key : pools.getKeys(false)) {
ConfigurationSection missionSection = pools.getConfigurationSection(key);
@@ -32,6 +30,7 @@ public List generateDailyMissions(String missionDate) {
String type = missionSection.getString("type");
String target = missionSection.getString("target");
+ List additionalTargets = missionSection.getStringList("additional-targets");
String displayName = missionSection.getString("display-name");
int minRequired = missionSection.getInt("min-required");
int maxRequired = missionSection.getInt("max-required");
@@ -39,15 +38,12 @@ public List generateDailyMissions(String missionDate) {
int maxXP = missionSection.getInt("max-xp");
int weight = missionSection.getInt("weight", 10);
- MissionTemplate template = new MissionTemplate(displayName, type, target,
+ MissionTemplate template = new MissionTemplate(displayName, type, target, additionalTargets,
minRequired, maxRequired, minXP, maxXP);
-
- uniqueTemplates.put(key, template);
weightedTemplates.add(new WeightedMissionTemplate(template, weight, key));
}
int missionsToGenerate = configManager.getDailyMissionsCount();
- Set usedMissionKeys = new HashSet<>();
for (int i = 0; i < missionsToGenerate && !weightedTemplates.isEmpty(); i++) {
WeightedMissionTemplate selected = selectWeightedRandom(weightedTemplates);
@@ -55,7 +51,6 @@ public List generateDailyMissions(String missionDate) {
if (selected != null) {
Mission mission = createMissionFromTemplate(selected.template);
newMissions.add(mission);
- usedMissionKeys.add(selected.key);
weightedTemplates.removeIf(w -> w.key.equals(selected.key));
}
@@ -96,7 +91,7 @@ private Mission createMissionFromTemplate(MissionTemplate template) {
.replace("", String.valueOf(required))
.replace("", formatTarget(template.target));
- return new Mission(name, template.type, template.target, required, xpReward);
+ return new Mission(name, template.type, template.target, template.additionalTargets, required, xpReward);
}
private String formatTarget(String target) {
diff --git a/src/main/java/com/Lino/battlePass/managers/MissionManager.java b/src/main/java/com/Lino/battlePass/managers/MissionManager.java
index 776235a..80de461 100644
--- a/src/main/java/com/Lino/battlePass/managers/MissionManager.java
+++ b/src/main/java/com/Lino/battlePass/managers/MissionManager.java
@@ -10,7 +10,7 @@
import java.time.LocalDateTime;
import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CompletableFuture;
public class MissionManager {
@@ -82,7 +82,7 @@ private void loadMissionsAfterSeasonData() {
if (resetHandler.getNextMissionReset() != null && now.isAfter(resetHandler.getNextMissionReset())) {
currentMissionDate = now.toLocalDate().toString();
databaseManager.clearOldMissionProgress(currentMissionDate);
- progressTracker.resetProgress(currentMissionDate);
+ progressTracker.resetProgress();
}
generateDailyMissions();
@@ -110,7 +110,7 @@ private void generateDailyMissions() {
currentMissionDate = LocalDateTime.now().toLocalDate().toString();
}
- dailyMissions = new ArrayList<>(missionGenerator.generateDailyMissions(currentMissionDate));
+ dailyMissions = new ArrayList<>(missionGenerator.generateDailyMissions());
}
public void checkMissionReset() {
@@ -127,7 +127,7 @@ public void checkMissionReset() {
player.sendMessage(messageManager.getPrefix() + messageManager.getMessage("messages.mission.reset"));
}
- progressTracker.resetProgress(currentMissionDate);
+ progressTracker.resetProgress();
databaseManager.clearOldMissionProgress(currentMissionDate);
}
}
@@ -144,7 +144,7 @@ private void resetSeason() {
generateDailyMissions();
resetHandler.calculateNextReset();
saveSeasonData();
- progressTracker.resetProgress(currentMissionDate);
+ progressTracker.resetProgress();
}
public void forceResetSeason() {
@@ -153,7 +153,7 @@ public void forceResetSeason() {
generateDailyMissions();
saveDailyMissions();
saveSeasonData();
- progressTracker.resetProgress(currentMissionDate);
+ progressTracker.resetProgress();
Bukkit.getScheduler().runTaskLater(plugin, () -> {
if (plugin.getCoinsDistributionTask() != null) {
@@ -180,8 +180,8 @@ public void forceResetMissions() {
player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0f, 1.0f);
}
- progressTracker.resetProgress(currentMissionDate);
- databaseManager.clearOldMissionProgress(currentMissionDate);
+ progressTracker.resetProgress();
+ databaseManager.clearOldMissionProgress(LocalDateTime.now().plusDays(1).toLocalDate().toString());
}
public void progressMission(Player player, String type, String target, int amount) {
diff --git a/src/main/java/com/Lino/battlePass/managers/MissionProgressTracker.java b/src/main/java/com/Lino/battlePass/managers/MissionProgressTracker.java
index e4d8358..c7136f1 100644
--- a/src/main/java/com/Lino/battlePass/managers/MissionProgressTracker.java
+++ b/src/main/java/com/Lino/battlePass/managers/MissionProgressTracker.java
@@ -37,7 +37,7 @@ public void trackProgress(Player player, String type, String target, int amount,
for (Mission mission : dailyMissions) {
if (!mission.type.equals(type)) continue;
- if (!mission.target.equals("ANY") && !mission.target.equals(target)) continue;
+ if (!mission.isValidTarget(target)) continue;
String missionKey = generateMissionKey(mission);
@@ -83,7 +83,7 @@ private String generateMissionKey(Mission mission) {
return mission.type + "_" + mission.target + "_" + mission.required + "_" + mission.name.hashCode();
}
- public void resetProgress(String currentMissionDate) {
+ public void resetProgress() {
playerCompletedMissions.clear();
lastActionbarUpdate.clear();
@@ -116,7 +116,7 @@ private void checkLevelUp(Player player, PlayerData data) {
"%level%", String.valueOf(data.level)));
player.playSound(player.getLocation(), Sound.UI_TOAST_CHALLENGE_COMPLETE, 1.0f, 1.0f);
- int available = plugin.getRewardManager().countAvailableRewards(player, data);
+ int available = plugin.getRewardManager().countAvailableRewards(data);
if (available > 0) {
player.sendMessage(messageManager.getPrefix() + messageManager.getMessage("messages.new-rewards"));
}
diff --git a/src/main/java/com/Lino/battlePass/managers/RewardManager.java b/src/main/java/com/Lino/battlePass/managers/RewardManager.java
index 3e34a00..9033d45 100644
--- a/src/main/java/com/Lino/battlePass/managers/RewardManager.java
+++ b/src/main/java/com/Lino/battlePass/managers/RewardManager.java
@@ -22,8 +22,6 @@ public class RewardManager {
private final BattlePass plugin;
private final ConfigManager configManager;
- private final List freeRewards = new ArrayList<>();
- private final List premiumRewards = new ArrayList<>();
private final Map> freeRewardsByLevel = new HashMap<>();
private final Map> premiumRewardsByLevel = new HashMap<>();
@@ -36,8 +34,6 @@ public RewardManager(BattlePass plugin, ConfigManager configManager) {
}
public void loadRewards() {
- freeRewards.clear();
- premiumRewards.clear();
freeRewardsByLevel.clear();
premiumRewardsByLevel.clear();
@@ -57,14 +53,12 @@ public void loadRewards() {
if (freeConfig.contains(levelPath + ".material") || freeConfig.contains(levelPath + ".command")) {
Reward reward = loadSingleReward(freeConfig, levelPath, i, true);
if (reward != null) {
- freeRewards.add(reward);
freeLevel.add(reward);
}
} else if (freeConfig.contains(levelPath + ".items")) {
for (String key : freeConfig.getConfigurationSection(levelPath + ".items").getKeys(false)) {
Reward reward = loadSingleReward(freeConfig, levelPath + ".items." + key, i, true);
if (reward != null) {
- freeRewards.add(reward);
freeLevel.add(reward);
}
}
@@ -75,14 +69,12 @@ public void loadRewards() {
if (premiumConfig.contains(levelPath + ".material") || premiumConfig.contains(levelPath + ".command")) {
Reward reward = loadSingleReward(premiumConfig, levelPath, i, false);
if (reward != null) {
- premiumRewards.add(reward);
premiumLevel.add(reward);
}
} else if (premiumConfig.contains(levelPath + ".items")) {
for (String key : premiumConfig.getConfigurationSection(levelPath + ".items").getKeys(false)) {
Reward reward = loadSingleReward(premiumConfig, levelPath + ".items." + key, i, false);
if (reward != null) {
- premiumRewards.add(reward);
premiumLevel.add(reward);
}
}
@@ -103,7 +95,8 @@ private void updateMaxLevel(FileConfiguration config) {
if (level > maxLevel) {
maxLevel = level;
}
- } catch (NumberFormatException ignored) {}
+ } catch (NumberFormatException ignored) {
+ }
}
}
}
@@ -235,7 +228,7 @@ public void claimRewards(Player player, PlayerData data, List rewards,
plugin.getPlayerDataManager().markForSave(player.getUniqueId());
}
- public int countAvailableRewards(Player player, PlayerData data) {
+ public int countAvailableRewards(PlayerData data) {
int count = 0;
for (int level : freeRewardsByLevel.keySet()) {
if (data.level >= level && !data.claimedFreeRewards.contains(level)) {
@@ -270,6 +263,10 @@ public int getMaxLevel() {
return maxLevel;
}
+ public int getMaxPage() {
+ return (int) Math.ceil(getMaxLevel() / 9.0);
+ }
+
public List getEditableRewards(int level, boolean isPremium) {
List editableRewards = new ArrayList<>();
FileConfiguration config = isPremium ?
diff --git a/src/main/java/com/Lino/battlePass/managers/ShopManager.java b/src/main/java/com/Lino/battlePass/managers/ShopManager.java
index 494b7b9..40cf9a0 100644
--- a/src/main/java/com/Lino/battlePass/managers/ShopManager.java
+++ b/src/main/java/com/Lino/battlePass/managers/ShopManager.java
@@ -20,7 +20,6 @@
public class ShopManager {
private final BattlePass plugin;
- private FileConfiguration shopConfig;
private final Map shopItems = new HashMap<>();
public ShopManager(BattlePass plugin) {
@@ -34,7 +33,7 @@ public void loadShop() {
plugin.saveResource("shop.yml", false);
}
- shopConfig = YamlConfiguration.loadConfiguration(shopFile);
+ FileConfiguration shopConfig = YamlConfiguration.loadConfiguration(shopFile);
shopItems.clear();
ConfigurationSection items = shopConfig.getConfigurationSection("shop-items");
diff --git a/src/main/java/com/Lino/battlePass/models/Mission.java b/src/main/java/com/Lino/battlePass/models/Mission.java
index 6c91633..d8fb10d 100644
--- a/src/main/java/com/Lino/battlePass/models/Mission.java
+++ b/src/main/java/com/Lino/battlePass/models/Mission.java
@@ -1,17 +1,29 @@
package com.Lino.battlePass.models;
+import java.util.List;
+import java.util.ArrayList;
+
public class Mission {
public final String name;
public final String type;
public final String target;
+ public final List additionalTargets;
public final int required;
public final int xpReward;
- public Mission(String name, String type, String target, int required, int xpReward) {
+ public Mission(String name, String type, String target, List additionalTargets, int required, int xpReward) {
this.name = name;
this.type = type;
this.target = target;
+ this.additionalTargets = additionalTargets != null ? additionalTargets : new ArrayList<>();
this.required = required;
this.xpReward = xpReward;
}
+
+ public boolean isValidTarget(String actionTarget) {
+ if ("ANY".equals(target) || target.equalsIgnoreCase(actionTarget)) {
+ return true;
+ }
+ return additionalTargets.stream().anyMatch(additional -> additional.equalsIgnoreCase(actionTarget));
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/Lino/battlePass/models/MissionTemplate.java b/src/main/java/com/Lino/battlePass/models/MissionTemplate.java
index 2626cb6..e595984 100644
--- a/src/main/java/com/Lino/battlePass/models/MissionTemplate.java
+++ b/src/main/java/com/Lino/battlePass/models/MissionTemplate.java
@@ -1,19 +1,24 @@
package com.Lino.battlePass.models;
+import java.util.List;
+import java.util.ArrayList;
+
public class MissionTemplate {
public final String nameFormat;
public final String type;
public final String target;
+ public final List additionalTargets;
public final int minRequired;
public final int maxRequired;
public final int minXP;
public final int maxXP;
- public MissionTemplate(String nameFormat, String type, String target, int minRequired,
- int maxRequired, int minXP, int maxXP) {
+ public MissionTemplate(String nameFormat, String type, String target, List additionalTargets,
+ int minRequired, int maxRequired, int minXP, int maxXP) {
this.nameFormat = nameFormat;
this.type = type;
this.target = target;
+ this.additionalTargets = additionalTargets != null ? additionalTargets : new ArrayList<>();
this.minRequired = minRequired;
this.maxRequired = maxRequired;
this.minXP = minXP;
diff --git a/src/main/java/com/Lino/battlePass/placeholders/BattlePassExpansion.java b/src/main/java/com/Lino/battlePass/placeholders/BattlePassExpansion.java
index 2d15ad7..b5c4456 100644
--- a/src/main/java/com/Lino/battlePass/placeholders/BattlePassExpansion.java
+++ b/src/main/java/com/Lino/battlePass/placeholders/BattlePassExpansion.java
@@ -91,7 +91,7 @@ public String onRequest(OfflinePlayer player, String identifier) {
case "available_rewards":
if (player.isOnline()) {
Player onlinePlayer = player.getPlayer();
- return String.valueOf(plugin.getRewardManager().countAvailableRewards(onlinePlayer, data));
+ return String.valueOf(plugin.getRewardManager().countAvailableRewards(data));
}
return "0";
diff --git a/src/main/java/com/Lino/battlePass/tasks/BattlePassTask.java b/src/main/java/com/Lino/battlePass/tasks/BattlePassTask.java
index ac22845..538859b 100644
--- a/src/main/java/com/Lino/battlePass/tasks/BattlePassTask.java
+++ b/src/main/java/com/Lino/battlePass/tasks/BattlePassTask.java
@@ -44,7 +44,7 @@ private void checkRewardNotifications() {
PlayerData data = plugin.getPlayerDataManager().getPlayerData(player.getUniqueId());
if (data == null) continue;
- int availableRewards = plugin.getRewardManager().countAvailableRewards(player, data);
+ int availableRewards = plugin.getRewardManager().countAvailableRewards(data);
if (availableRewards > data.lastNotification) {
player.sendMessage(plugin.getMessageManager().getPrefix() +
diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml
index 739933f..36ee36a 100644
--- a/src/main/resources/messages.yml
+++ b/src/main/resources/messages.yml
@@ -128,7 +128,7 @@ items:
name: "⭐ Your Progress"
lore:
- "&7"
- - "&8▸ &7Level: %level%&7/54"
+ - "&8▸ &7Level: %level%&7/%max_level%"
- "&8▸ &7XP: %xp%&7/%xp_needed%"
- "&7"
- "&8▸ &7Premium Pass: %premium_status%"
diff --git a/src/main/resources/missions.yml b/src/main/resources/missions.yml
index 452244b..775219e 100644
--- a/src/main/resources/missions.yml
+++ b/src/main/resources/missions.yml
@@ -5,6 +5,10 @@ mission-pools:
kill-zombies:
type: KILL_MOB
target: ZOMBIE
+ additional-targets:
+ - ZOMBIE_VILLAGER
+ - DROWNED
+ - HUSK
display-name: "Kill Zombies"
min-required: 15
max-required: 40
@@ -15,6 +19,9 @@ mission-pools:
kill-skeletons:
type: KILL_MOB
target: SKELETON
+ additional-targets:
+ - STRAY
+ - BOGGED
display-name: "Kill Skeletons"
min-required: 15
max-required: 35
@@ -25,6 +32,8 @@ mission-pools:
kill-spiders:
type: KILL_MOB
target: SPIDER
+ additional-targets:
+ - CAVE_SPIDER
display-name: "Kill Spiders"
min-required: 10
max-required: 30
@@ -97,6 +106,8 @@ mission-pools:
mine-coal:
type: MINE_BLOCK
target: COAL_ORE
+ additional-targets:
+ - DEEPSLATE_COAL_ORE
display-name: "Mine Coal Ores"
min-required: 30
max-required: 100
@@ -107,6 +118,8 @@ mission-pools:
mine-iron:
type: MINE_BLOCK
target: IRON_ORE
+ additional-targets:
+ - DEEPSLATE_IRON_ORE
display-name: "Mine Iron Ores"
min-required: 20
max-required: 60
@@ -117,6 +130,8 @@ mission-pools:
mine-gold:
type: MINE_BLOCK
target: GOLD_ORE
+ additional-targets:
+ - DEEPSLATE_GOLD_ORE
display-name: "Mine Gold Ores"
min-required: 10
max-required: 30
@@ -127,26 +142,20 @@ mission-pools:
mine-diamonds:
type: MINE_BLOCK
target: DIAMOND_ORE
+ additional-targets:
+ - DEEPSLATE_DIAMOND_ORE
display-name: "Mine Diamond Ores"
min-required: 5
max-required: 15
- min-xp: 400
- max-xp: 600
- weight: 6
-
- mine-deepslate-diamonds:
- type: MINE_BLOCK
- target: DEEPSLATE_DIAMOND_ORE
- display-name: "Mine Deepslate Diamonds"
- min-required: 5
- max-required: 15
- min-xp: 450
- max-xp: 650
+ min-xp: 425
+ max-xp: 625
weight: 6
mine-lapis:
type: MINE_BLOCK
target: LAPIS_ORE
+ additional-targets:
+ - DEEPSLATE_LAPIS_ORE
display-name: "Mine Lapis Ores"
min-required: 15
max-required: 40
@@ -157,6 +166,8 @@ mission-pools:
mine-redstone:
type: MINE_BLOCK
target: REDSTONE_ORE
+ additional-targets:
+ - DEEPSLATE_REDSTONE_ORE
display-name: "Mine Redstone Ores"
min-required: 20
max-required: 50
@@ -188,6 +199,10 @@ mission-pools:
break-logs:
type: BREAK_BLOCK
target: OAK_LOG
+ additional-targets:
+ - STRIPPED_OAK_LOG
+ - OAK_WOOD
+ - STRIPPED_OAK_WOOD
display-name: "Chop Oak Logs"
min-required: 64
max-required: 200
@@ -205,6 +220,24 @@ mission-pools:
max-xp: 200
weight: 9
+ break-dirt:
+ type: BREAK_BLOCK
+ target: DIRT
+ additional-targets:
+ - GRASS_BLOCK
+ - COARSE_DIRT
+ - ROOTED_DIRT
+ - PODZOL
+ - MYCELIUM
+ - DIRT_PATH
+ - FARMLAND
+ display-name: "Break Dirt"
+ min-required: 200
+ max-required: 500
+ min-xp: 80
+ max-xp: 160
+ weight: 9
+
eat-bread:
type: EAT_ITEM
target: BREAD
@@ -235,6 +268,29 @@ mission-pools:
max-xp: 800
weight: 4
+ # Place blocks
+ place-wood:
+ type: PLACE_BLOCK
+ target: OAK_PLANKS
+ additional-targets:
+ - SPRUCE_PLANKS
+ - BIRCH_PLANKS
+ - JUNGLE_PLANKS
+ - ACACIA_PLANKS
+ - DARK_OAK_PLANKS
+ - MANGROVE_PLANKS
+ - CHERRY_PLANKS
+ - BAMBOO_PLANKS
+ - CRIMSON_PLANKS
+ - WARPED_PLANKS
+ - PALE_OAK_PLANKS
+ display-name: "Place Planks"
+ min-required: 64
+ max-required: 200
+ min-xp: 80
+ max-xp: 150
+ weight: 9
+
# Crafting & Smelting
smelt-iron:
type: SMELT_ITEM
@@ -301,6 +357,8 @@ mission-pools:
breed-cows:
type: BREED_ANIMAL
target: COW
+ additional-targets:
+ - MOOSHROOM
display-name: "Breed Cows"
min-required: 5
max-required: 20
@@ -338,53 +396,250 @@ mission-pools:
max-xp: 500
weight: 5
- trade-villager:
+ # Trade missions
+ # Supported targets: ANY, FARMER, FISHERMAN, SHEPHERD, FLETCHER, LIBRARIAN, CARTOGRAPHER,
+ # CLERIC, ARMORER, WEAPONSMITH, TOOLSMITH, BUTCHER, LEATHERWORKER, MASON, MERCHANT
+ trade-agriculture:
type: TRADE_VILLAGER
- target: ANY
- display-name: "Trade Times with Villagers"
+ target: FARMER
+ additional-targets:
+ - FISHERMAN
+ - SHEPHERD
+ - BUTCHER
+ display-name: "Trade with Agriculture Villagers Times"
min-required: 5
max-required: 20
min-xp: 200
max-xp: 400
weight: 7
- enchant-items:
+ trade-crafters:
+ type: TRADE_VILLAGER
+ target: ARMORER
+ additional-targets:
+ - WEAPONSMITH
+ - TOOLSMITH
+ - FLETCHER
+ - LEATHERWORKER
+ - MASON
+ display-name: "Change with Crafters Villagers Times"
+ min-required: 5
+ max-required: 20
+ min-xp: 200
+ max-xp: 400
+ weight: 7
+
+ # Enchant missions
+ enchant-swords:
type: ENCHANT_ITEM
- target: ANY
- display-name: "Enchant Items"
+ target: DIAMOND_SWORD
+ additional-targets:
+ - NETHERITE_SWORD
+ - IRON_SWORD
+ - GOLDEN_SWORD
+ - STONE_SWORD
+ - WOODEN_SWORD
+ display-name: "Enchant swords"
min-required: 3
max-required: 10
min-xp: 250
max-xp: 500
weight: 6
- # General Progression
- gain-xp:
- type: GAIN_XP
- target: ANY
- display-name: "Gain XP Points"
- min-required: 500
- max-required: 2000
+ enchant-armor:
+ type: ENCHANT_ITEM
+ target: DIAMOND_CHESTPLATE
+ additional-targets:
+ - NETHERITE_HELMET
+ - NETHERITE_CHESTPLATE
+ - NETHERITE_LEGGINGS
+ - NETHERITE_BOOTS
+ - DIAMOND_HELMET
+ - DIAMOND_LEGGINGS
+ - DIAMOND_BOOTS
+ - IRON_HELMET
+ - IRON_CHESTPLATE
+ - IRON_LEGGINGS
+ - IRON_BOOTS
+ - GOLDEN_HELMET
+ - GOLDEN_CHESTPLATE
+ - GOLDEN_LEGGINGS
+ - GOLDEN_BOOTS
+ - LEATHER_HELMET
+ - LEATHER_CHESTPLATE
+ - LEATHER_LEGGINGS
+ - LEATHER_BOOTS
+ - CHAINMAIL_HELMET
+ - CHAINMAIL_CHESTPLATE
+ - CHAINMAIL_LEGGINGS
+ - CHAINMAIL_BOOTS
+ display-name: "Enchant armors"
+ min-required: 3
+ max-required: 10
+ min-xp: 250
+ max-xp: 500
+ weight: 6
+
+ # DamageDeal missions
+ # Supported targets: ANY, PLAYER, ANY MOBS
+ damage-sea-creatures:
+ type: DAMAGE_DEALT
+ target: GUARDIAN
+ additional-targets:
+ - ELDER_GUARDIAN
+ - SQUID
+ - GLOW_SQUID
+ - DOLPHIN
+ - TURTLE
+ - COD
+ - SALMON
+ - PUFFERFISH
+ - TROPICAL_FISH
+ - AXOLOTL
+ display-name: "Deal Damage to sea creatures"
+ min-required: 700
+ max-required: 3500
min-xp: 200
max-xp: 400
+ weight: 7
+
+ damage-nether-creatures:
+ type: DAMAGE_DEALT
+ target: ZOMBIFIED_PIGLIN
+ additional-targets:
+ - BLAZE
+ - GHAST
+ - MAGMA_CUBE
+ - WITHER_SKELETON
+ - PIGLIN
+ - PIGLIN_BRUTE
+ - HOGLIN
+ - ZOGLIN
+ - STRIDER
+ display-name: "Deal Damage to nether creatures"
+ min-required: 700
+ max-required: 3500
+ min-xp: 200
+ max-xp: 400
+ weight: 7
+
+ damage-end-creatures:
+ type: DAMAGE_DEALT
+ target: ENDERMAN
+ additional-targets:
+ - ENDERMITE
+ - SHULKER
+ - ENDER_DRAGON
+ display-name: "Deal Damage to end creatures"
+ min-required: 450
+ max-required: 1500
+ min-xp: 190
+ max-xp: 370
+ weight: 4
+
+ damage-overworld-animals:
+ type: DAMAGE_DEALT
+ target: COW
+ additional-targets:
+ - PIG
+ - SHEEP
+ - CHICKEN
+ - RABBIT
+ - FOX
+ - PANDA
+ - BEE
+ - POLAR_BEAR
+ - WOLF
+ - OCELOT
+ - CAT
+ - PARROT
+ - DONKEY
+ - HORSE
+ - MULE
+ - LLAMA
+ - TRADER_LLAMA
+ - GOAT
+ - FROG
+ - TADPOLE
+ display-name: "Deal Damage to overworld animals"
+ min-required: 500
+ max-required: 2500
+ min-xp: 160
+ max-xp: 320
weight: 8
- walk-distance:
+ damage-flying-creatures:
+ type: DAMAGE_DEALT
+ target: GHAST
+ additional-targets:
+ - BLAZE
+ - PHANTOM
+ - BAT
+ - PARROT
+ - BEE
+ - ENDER_DRAGON
+ - WITHER
+ display-name: "Deal Damage to Flying creatures"
+ min-required: 250
+ max-required: 1500
+ min-xp: 190
+ max-xp: 370
+ weight: 4
+
+ #DamageTaken missions
+ # Supported targets: ANY, PLAYER, ANY MOBS, FIRE, LAVA, FALL, DROWNING, POISON,
+ # EXPLOSION, VOID, STARVATION, CONTACT
+ take-damage-fall:
+ type: DAMAGE_TAKEN
+ target: FALL
+ display-name: "Take Damage from fall"
+ min-required: 25
+ max-required: 75
+ min-xp: 100
+ max-xp: 200
+ weight: 9
+
+ take-damage-fire:
+ type: DAMAGE_TAKEN
+ target: FIRE
+ additional-targets:
+ - LAVA
+ display-name: "Take Damage from fire"
+ min-required: 50
+ max-required: 150
+ min-xp: 100
+ max-xp: 200
+ weight: 9
+
+ # WalkDistance missions
+ # Supported targets: ANY, WALK, SWIM, FLY, SHIFT
+ move-distance:
type: WALK_DISTANCE
target: ANY
- display-name: "Walk Blocks"
+ display-name: "Move Blocks"
min-required: 2000
max-required: 10000
min-xp: 150
max-xp: 300
weight: 9
- deal-damage:
- type: DAMAGE_DEALT
+ swim-distance:
+ type: WALK_DISTANCE
+ target: SWIM
+ display-name: "Swim Blocks"
+ min-required: 1500
+ max-required: 7500
+ min-xp: 160
+ max-xp: 320
+ weight: 8
+
+ # General Progression
+ gain-xp:
+ type: GAIN_XP
target: ANY
- display-name: "Deal Damage"
- min-required: 1000
- max-required: 5000
+ display-name: "Gain XP Points"
+ min-required: 500
+ max-required: 2000
min-xp: 200
max-xp: 400
weight: 8