diff --git a/CHANGES.md b/CHANGES.md
index e6e0ed1b..9c020ea9 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,11 +1,13 @@
**New Plugin [Infinite Elytra Parkour](https://www.spigotmc.org/resources/115322/) | [IP+](https://www.spigotmc.org/resources/105019/)**
-- Fixed schematics being unusable when it contains unknown materials
-- Fixed difficulty going above 1
-- Fixed schematic points being based on all settings difficulty, not schematic difficulty
-- Fixed inventories not being cleared
-- Fixed inventories being cleared on leave with inventory handling off
-- Fixed teleporting not being async when possible
-- Fixed incorrect rewards documentation
-- Added debugging messages
-- Improved unsupported schematic message clarity
\ No newline at end of file
+- Added item for IEP support
+- Added option to disable players opening blocks with inventories
+- Fixed players occasionally being reset to previous location while switching mode
+- Fixed errors showing up in console on disable when nobody joined parkour
+- Fixed world being deleted even if delete-on-reload is enabled
+- Fixed not loading if delete-on-reload is enabled with Multiverse worlds
+- Fixed bad parkour pathfinding near edges
+- Fixed player mounting causing issues
+- Fixed players being able to transfer inventory items with some plugins
+- Fixed not being able to close leaderboard if not using IP+
+- Fixed errors when joining as spectator
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 4177e0c6..330b4e1c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
dev.efnilite
IP
- 5.2.0
+ 5.2.1
16
@@ -97,7 +97,7 @@
com.github.Efnilite
vilib
- ed66743ad8
+ 66840fa513
compile
diff --git a/src/main/java/dev/efnilite/ip/Command.java b/src/main/java/dev/efnilite/ip/Command.java
index 09db623a..3de12bf8 100644
--- a/src/main/java/dev/efnilite/ip/Command.java
+++ b/src/main/java/dev/efnilite/ip/Command.java
@@ -138,7 +138,7 @@ private void sendHelpMessages(CommandSender sender) {
send(sender, "");
send(sender, "/parkour - Main command");
if (sender.hasPermission(ParkourOption.JOIN.permission)) {
- send(sender, "/parkour join [mode] - Join the default mode or specify one.");
+ send(sender, "/parkour join [mode/player] - Join the default mode or specify one.");
send(sender, "/parkour leave - Leave the game on this server");
}
if (sender.hasPermission(ParkourOption.MAIN.permission)) {
diff --git a/src/main/java/dev/efnilite/ip/Events.java b/src/main/java/dev/efnilite/ip/Events.java
index fe6093b7..1208416b 100644
--- a/src/main/java/dev/efnilite/ip/Events.java
+++ b/src/main/java/dev/efnilite/ip/Events.java
@@ -28,6 +28,7 @@
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.entity.EntityMountEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.*;
@@ -80,7 +81,7 @@ public void join(PlayerJoinEvent event) {
if (player.isOp() && WorldManagerMV.MANAGER != null && VoidGenerator.getMultiverseGenerator() == null) {
send(player, "");
- send(player, IP.PREFIX + "You are running Multiverse without VoidGen. This causes extreme lag spikes and performance issues while playing. Please visit the wiki to fix this.");
+ send(player, IP.PREFIX + "You are running Multiverse without VoidGen. This causes extreme lag spikes and performance issues while playing. Please install the plugin 'VoidGen' to fix this.");
send(player, "");
}
@@ -227,7 +228,9 @@ public void interact(PlayerInteractEvent event) {
} else if (held == quit) {
ParkourUser.leave(player);
} else {
- event.setCancelled(false);
+ if (!Config.CONFIG.getBoolean("options.disable-inventory-blocks")) {
+ event.setCancelled(false);
+ }
}
}
@@ -278,7 +281,7 @@ public void damage(EntityDamageEvent event) {
handleRestriction(player, event);
}
- @EventHandler
+ @EventHandler(priority = EventPriority.HIGHEST)
public void inventory(InventoryClickEvent event) {
if (!(event.getWhoClicked() instanceof Player player) || event.getInventory().getType() == InventoryType.CRAFTING) {
return;
@@ -296,6 +299,15 @@ public void spectate(PlayerTeleportEvent event) {
handleRestriction(event.getPlayer(), event);
}
+ @EventHandler(priority = EventPriority.HIGHEST)
+ public void mount(EntityMountEvent event) {
+ if (!(event.getEntity() instanceof Player player)) {
+ return;
+ }
+
+ handleRestriction(player, event);
+ }
+
private void handleRestriction(Player player, Cancellable event) {
if (!ParkourUser.isUser(player)) {
return;
diff --git a/src/main/java/dev/efnilite/ip/IP.java b/src/main/java/dev/efnilite/ip/IP.java
index 4d9f7bf1..89be9cb3 100644
--- a/src/main/java/dev/efnilite/ip/IP.java
+++ b/src/main/java/dev/efnilite/ip/IP.java
@@ -19,7 +19,6 @@
import dev.efnilite.vilib.bstats.charts.SingleLineChart;
import dev.efnilite.vilib.inventory.Menu;
import dev.efnilite.vilib.util.Logging;
-import dev.efnilite.vilib.util.elevator.GitElevator;
import org.jetbrains.annotations.Nullable;
import java.io.File;
@@ -107,20 +106,19 @@ public void enable() {
@Override
public void disable() {
- for (ParkourUser user : ParkourUser.getUsers()) {
- ParkourUser.leave(user);
- }
+ try {
+ for (ParkourUser user : ParkourUser.getUsers()) {
+ ParkourUser.leave(user);
+ }
- // write all IP gamemodes
- Modes.DEFAULT.getLeaderboard().write(false);
+ // write all IP gamemodes
+ Modes.DEFAULT.getLeaderboard().write(false);
- Storage.close();
- WorldManager.delete();
- }
+ Storage.close();
+ WorldManager.delete();
+ } catch (Throwable ignored) {
- @Override
- public GitElevator getElevator() {
- return null;
+ }
}
public static void log(String message) {
diff --git a/src/main/java/dev/efnilite/ip/config/Config.java b/src/main/java/dev/efnilite/ip/config/Config.java
index d618acae..9994887d 100644
--- a/src/main/java/dev/efnilite/ip/config/Config.java
+++ b/src/main/java/dev/efnilite/ip/config/Config.java
@@ -49,7 +49,6 @@ public enum Config {
if (!path.exists()) {
IP.getPlugin().saveResource(fileName, false);
- IP.log("Created config file %s".formatted(fileName));
}
update();
diff --git a/src/main/java/dev/efnilite/ip/generator/Island.java b/src/main/java/dev/efnilite/ip/generator/Island.java
index 562e6c37..68b0fa48 100644
--- a/src/main/java/dev/efnilite/ip/generator/Island.java
+++ b/src/main/java/dev/efnilite/ip/generator/Island.java
@@ -3,7 +3,6 @@
import dev.efnilite.ip.IP;
import dev.efnilite.ip.config.Config;
import dev.efnilite.ip.session.Session;
-import dev.efnilite.ip.world.Divider;
import dev.efnilite.vilib.schematic.Schematic;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -44,22 +43,20 @@ public Island(@NotNull Session session, @Nullable Schematic schematic) {
/**
* Builds the island and teleports the player.
*/
- public void build() {
+ public void build(Location location) {
if (schematic == null) {
return;
}
IP.log("Building island");
- IP.log("Building island");
-
- blocks = schematic.paste(Divider.toLocation(session).subtract(0, schematic.getDimensions().getY(), 0));
+ blocks = schematic.paste(location.subtract(0, schematic.getDimensions().getY(), 0));
Material playerMaterial = Material.getMaterial(Config.GENERATION.getString("advanced.island.spawn.player-block").toUpperCase());
Material parkourMaterial = Material.getMaterial(Config.GENERATION.getString("advanced.island.parkour.begin-block").toUpperCase());
try {
- Block player = blocks.stream().filter(block -> block.getType() == playerMaterial).findAny().get();
- Block parkour = blocks.stream().filter(block -> block.getType() == parkourMaterial).findAny().get();
+ Block player = blocks.stream().filter(block -> block.getType() == playerMaterial).findAny().orElseThrow();
+ Block parkour = blocks.stream().filter(block -> block.getType() == parkourMaterial).findAny().orElseThrow();
player.setType(Material.AIR);
parkour.setType(Material.AIR);
diff --git a/src/main/java/dev/efnilite/ip/generator/JumpDirector.java b/src/main/java/dev/efnilite/ip/generator/JumpDirector.java
index 9a2f2a81..59655d83 100644
--- a/src/main/java/dev/efnilite/ip/generator/JumpDirector.java
+++ b/src/main/java/dev/efnilite/ip/generator/JumpDirector.java
@@ -68,10 +68,10 @@ private double[][] calculateParameterization(@NotNull Vector point) {
* the heading will automatically be turned around to ensure that the edge does not get
* destroyed.
*
- * @return The recommended new heading. (0,0,0) if no modification is needed.
+ * @return The recommended new heading. Current heading if no modification is needed.
*/
@NotNull
- public Vector getRecommendedHeading() {
+ public Vector getRecommendedHeading(Vector current) {
// get x values from progress array
double tx = progress[0][0];
double borderMarginX = progress[0][1];
@@ -84,21 +84,25 @@ public Vector getRecommendedHeading() {
// check border
if (tx < borderMarginX) {
// x should increase
- recommendedHeading.add(new Vector(1, 0, 0));
+ recommendedHeading = new Vector(1, 0, 1);
} else if (tx > 1 - borderMarginX) {
// x should decrease
- recommendedHeading.add(new Vector(-1, 0, 0));
+ recommendedHeading = new Vector(-1, 0, -1);
}
if (tz < borderMarginZ) {
// z should increase
- recommendedHeading.add(new Vector(0, 0, 1));
+ recommendedHeading = new Vector(1, 0, 1);
} else if (tz > 1 - borderMarginZ) {
// z should decrease
- recommendedHeading.add(new Vector(0, 0, -1));
+ recommendedHeading = new Vector(-1, 0, -1);
}
- return recommendedHeading;
+ if (recommendedHeading.isZero()) {
+ return current;
+ } else {
+ return recommendedHeading;
+ }
}
/**
@@ -109,7 +113,7 @@ public Vector getRecommendedHeading() {
*
* @return The recommended new height. 0 if no modification is needed.
*/
- public int getRecommendedHeight() {
+ public int getRecommendedHeight(int current) {
double ty = progress[1][0];
double borderMarginY = progress[1][1];
@@ -120,7 +124,7 @@ public int getRecommendedHeight() {
// y should decrease
return -1;
}
- return 0;
+ return current;
}
/**
diff --git a/src/main/java/dev/efnilite/ip/generator/ParkourGenerator.java b/src/main/java/dev/efnilite/ip/generator/ParkourGenerator.java
index 72dda25a..f26bd3fd 100644
--- a/src/main/java/dev/efnilite/ip/generator/ParkourGenerator.java
+++ b/src/main/java/dev/efnilite/ip/generator/ParkourGenerator.java
@@ -304,17 +304,8 @@ protected List selectBlocks() {
protected Block selectNext(Block current, int distance, int height) {
JumpDirector director = new JumpDirector(BoundingBox.of(zone[0], zone[1]), getLatest().getLocation().toVector());
- Vector recommendedHeading = director.getRecommendedHeading();
-
- if (!recommendedHeading.equals(new Vector(0, 0, 0))) {
- heading = recommendedHeading;
- }
-
- int recommendedHeight = director.getRecommendedHeight();
-
- if (recommendedHeight != 0) {
- height = recommendedHeight;
- }
+ heading = director.getRecommendedHeading(heading);
+ height = director.getRecommendedHeight(height);
// ensure special is possible
switch (getLatest().getType()) {
diff --git a/src/main/java/dev/efnilite/ip/menu/community/SingleLeaderboardMenu.java b/src/main/java/dev/efnilite/ip/menu/community/SingleLeaderboardMenu.java
index 4055422d..17ea6160 100644
--- a/src/main/java/dev/efnilite/ip/menu/community/SingleLeaderboardMenu.java
+++ b/src/main/java/dev/efnilite/ip/menu/community/SingleLeaderboardMenu.java
@@ -1,6 +1,7 @@
package dev.efnilite.ip.menu.community;
import dev.efnilite.ip.IP;
+import dev.efnilite.ip.api.Registry;
import dev.efnilite.ip.config.Locales;
import dev.efnilite.ip.config.Option;
import dev.efnilite.ip.leaderboard.Leaderboard;
@@ -118,7 +119,19 @@ public void open(Player player, Mode mode, Sort sort) {
.nextPage(26, new Item(Material.LIME_DYE, "<#0DCB07>»").click(event -> menu.page(1)))
.prevPage(18, new Item(Material.RED_DYE, "<#DE1F1F>«").click(event -> menu.page(-1)))
.item(22, Locales.getItem(player, ParkourOption.LEADERBOARDS.path + ".sort", name.toLowerCase()).click(event -> open(player, mode, next)))
- .item(23, Locales.getItem(player, "other.close").click(event -> Menus.LEADERBOARDS.open(event.getPlayer())))
+ .item(23, Locales.getItem(player, "other.close").click(event -> {
+ List modes = Registry.getModes()
+ .stream()
+ .filter(m -> m.getLeaderboard() != null && m.getItem(locale) != null)
+ .toList();
+
+ if (modes.size() == 1) {
+ Menus.COMMUNITY.open(player);
+ return;
+ }
+
+ Menus.LEADERBOARDS.open(event.getPlayer());
+ }))
.fillBackground(ParkourUser.isBedrockPlayer(player) ? Material.AIR : Material.GRAY_STAINED_GLASS_PANE)
.open(player);
}
diff --git a/src/main/java/dev/efnilite/ip/menu/play/PlayMenu.java b/src/main/java/dev/efnilite/ip/menu/play/PlayMenu.java
index 3ed99a2d..1e05d2c8 100644
--- a/src/main/java/dev/efnilite/ip/menu/play/PlayMenu.java
+++ b/src/main/java/dev/efnilite/ip/menu/play/PlayMenu.java
@@ -7,6 +7,7 @@
import dev.efnilite.ip.player.ParkourUser;
import dev.efnilite.vilib.inventory.Menu;
import dev.efnilite.vilib.inventory.animation.RandomAnimation;
+import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
@@ -16,9 +17,21 @@
public class PlayMenu extends DynamicMenu {
public PlayMenu() {
- registerMainItem(1, 0, (player, user) -> Locales.getItem(player, "play.single.item").click(event -> Menus.SINGLE.open(event.getPlayer())), ParkourOption.SINGLE::mayPerform);
- registerMainItem(1, 2, (player, user) -> Locales.getItem(player, "play.spectator.item").click(event -> Menus.SPECTATOR.open(event.getPlayer())), ParkourOption.SPECTATOR::mayPerform);
- registerMainItem(2, 0, (player, user) -> Locales.getItem(player, "other.close").click(event -> event.getPlayer().closeInventory()), player -> true);
+ registerMainItem(1, 0, (player, user) -> Locales.getItem(player, "play.single.item")
+ .click(event -> Menus.SINGLE.open(event.getPlayer())),
+ ParkourOption.SINGLE::mayPerform);
+
+ registerMainItem(1, 1, (player, user) -> Locales.getItem(player, "other.iep")
+ .click(event -> event.getPlayer().performCommand("iep play")),
+ player -> Bukkit.getPluginManager().isPluginEnabled("IEP"));
+
+ registerMainItem(1, 6, (player, user) -> Locales.getItem(player, "play.spectator.item")
+ .click(event -> Menus.SPECTATOR.open(event.getPlayer())),
+ ParkourOption.SPECTATOR::mayPerform);
+
+ registerMainItem(2, 0, (player, user) -> Locales.getItem(player, "other.close")
+ .click(event -> event.getPlayer().closeInventory()),
+ player -> true);
}
public void open(Player player) {
diff --git a/src/main/java/dev/efnilite/ip/player/ParkourSpectator.java b/src/main/java/dev/efnilite/ip/player/ParkourSpectator.java
index 1b33fc83..bb416da2 100644
--- a/src/main/java/dev/efnilite/ip/player/ParkourSpectator.java
+++ b/src/main/java/dev/efnilite/ip/player/ParkourSpectator.java
@@ -79,6 +79,11 @@ public void update() {
player.setGameMode(GameMode.SPECTATOR);
updateScoreboard(session.generator);
+ // spectator is still being teleported to world
+ if (closest.getLocation().getWorld() != player.getLocation().getWorld()) {
+ return;
+ }
+
if (closest.getLocation().distanceSquared(player.getLocation()) < 100 * 100) { // avoid sqrt
return;
}
diff --git a/src/main/java/dev/efnilite/ip/player/ParkourUser.java b/src/main/java/dev/efnilite/ip/player/ParkourUser.java
index 5bf5395b..26db56f2 100644
--- a/src/main/java/dev/efnilite/ip/player/ParkourUser.java
+++ b/src/main/java/dev/efnilite/ip/player/ParkourUser.java
@@ -123,6 +123,8 @@ public static void unregister(@NotNull ParkourUser user, boolean restorePrevious
return;
}
+ if (!restorePreviousData) return;
+
user.previousData.apply(user.player, urgent);
if (user instanceof ParkourPlayer player) {
diff --git a/src/main/java/dev/efnilite/ip/player/data/PreviousData.java b/src/main/java/dev/efnilite/ip/player/data/PreviousData.java
index c8ea0262..1c5dcff6 100644
--- a/src/main/java/dev/efnilite/ip/player/data/PreviousData.java
+++ b/src/main/java/dev/efnilite/ip/player/data/PreviousData.java
@@ -58,11 +58,7 @@ public PreviousData(@NotNull Player player) {
inventoryData = null;
}
- // health handling after removing effects and inventory to avoid them affecting it
- if (Config.CONFIG.getBoolean("options.health-handling")) {
- player.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(20);
- player.setHealth(maxHealth);
- }
+ player.setHealth(maxHealth);
}
public void apply(Player player, boolean urgent) {
@@ -83,11 +79,7 @@ private void apply(Player player) {
player.setGameMode(gamemode);
player.setAllowFlight(allowFlight);
player.setFlying(flying);
-
- if (Config.CONFIG.getBoolean("options.health-handling")) {
- player.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(maxHealth);
- player.setHealth(health);
- }
+ player.setHealth(health);
for (PotionEffect effect : player.getActivePotionEffects()) {
player.removePotionEffect(effect.getType());
diff --git a/src/main/java/dev/efnilite/ip/session/Session.java b/src/main/java/dev/efnilite/ip/session/Session.java
index 59a4b03f..61c60db6 100644
--- a/src/main/java/dev/efnilite/ip/session/Session.java
+++ b/src/main/java/dev/efnilite/ip/session/Session.java
@@ -70,7 +70,7 @@ public static Session create(Function generatorFuncti
Session session = new Session();
- Divider.add(session);
+ var location = Divider.add(session);
if (isAcceptingPlayers != null) session.isAcceptingPlayers = isAcceptingPlayers;
if (isAcceptingSpectators != null) session.isAcceptingSpectators = isAcceptingSpectators;
@@ -90,7 +90,7 @@ public static Session create(Function generatorFuncti
pps.forEach(p -> p.updateGeneratorSettings(session.generator));
}
- session.generator.island.build();
+ session.generator.island.build(location);
return session;
}
diff --git a/src/main/java/dev/efnilite/ip/world/Divider.java b/src/main/java/dev/efnilite/ip/world/Divider.java
index cfc0b370..ec445ea2 100644
--- a/src/main/java/dev/efnilite/ip/world/Divider.java
+++ b/src/main/java/dev/efnilite/ip/world/Divider.java
@@ -29,7 +29,7 @@ public class Divider {
*
* @param session The session.
*/
- public static synchronized void add(Session session) {
+ public static synchronized Location add(Session session) {
// attempts to get the closest available section to the center
var missing = IntStream.range(0, sections.size() + 1)
.filter(i -> !sections.containsValue(i))
@@ -38,7 +38,11 @@ public static synchronized void add(Session session) {
sections.put(session, missing);
- IP.log("Added session at %s".formatted(Locations.toString(toLocation(session), true)));
+ var location = toLocation(session);
+
+ IP.log("Added session at %s".formatted(Locations.toString(location, true)));
+
+ return location;
}
/**
@@ -56,7 +60,7 @@ public static void remove(Session session) {
* @param session The session.
* @return The location at the center of section n.
*/
- public static Location toLocation(Session session) {
+ private static Location toLocation(Session session) {
int[] xz = spiralAt(sections.get(session));
return new Location(WorldManager.getWorld(),
@@ -65,7 +69,6 @@ public static Location toLocation(Session session) {
xz[1] * Option.BORDER_SIZE);
}
-
/**
* @param session The session.
* @return Array where the first item is the smallest location and second item is the largest.
diff --git a/src/main/java/dev/efnilite/ip/world/WorldManager.java b/src/main/java/dev/efnilite/ip/world/WorldManager.java
index 2a170791..542691eb 100644
--- a/src/main/java/dev/efnilite/ip/world/WorldManager.java
+++ b/src/main/java/dev/efnilite/ip/world/WorldManager.java
@@ -28,7 +28,7 @@ public interface WorldManager {
static void create() {
World world = getWorld();
- if (!Config.CONFIG.getBoolean("joining") || (!Config.CONFIG.getBoolean("world.delete-on-reload") && world != null)) {
+ if (!Config.CONFIG.getBoolean("joining")) {
return;
}
@@ -40,7 +40,10 @@ static void create() {
IP.log("Initializing world rules");
- manager.deleteWorld();
+ if (Config.CONFIG.getBoolean("world.delete-on-reload")) {
+ manager.deleteWorld();
+ }
+
world = manager.createWorld();
world.setGameRule(GameRule.DO_FIRE_TICK, false);
diff --git a/src/main/java/dev/efnilite/ip/world/WorldManagerMV.java b/src/main/java/dev/efnilite/ip/world/WorldManagerMV.java
index a6a273e9..ebdf755c 100644
--- a/src/main/java/dev/efnilite/ip/world/WorldManagerMV.java
+++ b/src/main/java/dev/efnilite/ip/world/WorldManagerMV.java
@@ -30,6 +30,13 @@ public World createWorld() {
if (MANAGER == null) {
return null;
}
+
+ // world has already been loaded
+ var existing = MANAGER.getMVWorld(Option.WORLD_NAME);
+ if (existing != null) {
+ return existing.getCBWorld();
+ }
+
IP.log("Creating MV world");
MANAGER.addWorld(Option.WORLD_NAME, World.Environment.NORMAL, null, WorldType.NORMAL, false, VoidGenerator.getMultiverseGenerator());
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index 93beabcf..0b429e26 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -158,10 +158,9 @@ options:
# This command will be executed by console.
alt-inventory-saving-command: ''
- # -= Health handling =-
- # Enables/disables the health handling system. This will reset (max) health to default values on join of the parkour.
- # Disable this if you're experiencing errors with max health, etc.
- health-handling: true
+ # -= Disables inventory blocks =-
+ # Disables the ability for a player to open blocks with an inventory.
+ disable-inventory-blocks: false
# -= Permissions options =-
# These permissions are used to determine which things the player can change.
diff --git a/src/main/resources/locales/en.yml b/src/main/resources/locales/en.yml
index c5368755..ac63aa5c 100644
--- a/src/main/resources/locales/en.yml
+++ b/src/main/resources/locales/en.yml
@@ -253,3 +253,8 @@ other:
material: "arrow"
name: "<#F5A3A3>Close"
lore: ""
+
+ iep:
+ material: "elytra"
+ name: "<#4800FF>Flying"
+ lore: "Parkour with elytra!"
\ No newline at end of file
diff --git a/src/main/resources/locales/fr.yml b/src/main/resources/locales/fr.yml
index 3b95f1a6..0ec5614b 100644
--- a/src/main/resources/locales/fr.yml
+++ b/src/main/resources/locales/fr.yml
@@ -253,3 +253,8 @@ other:
material: "arrow"
name: "<#F5A3A3>Fermé"
lore: ""
+
+ iep:
+ material: "elytra"
+ name: "<#4800FF>Flying"
+ lore: "Parkour with elytra!"
\ No newline at end of file
diff --git a/src/main/resources/locales/jp.yml b/src/main/resources/locales/jp.yml
index ab9e3874..f0d83760 100644
--- a/src/main/resources/locales/jp.yml
+++ b/src/main/resources/locales/jp.yml
@@ -252,4 +252,9 @@ other:
close:
material: "arrow"
name: "<#F5A3A3>戻る"
- lore: ""
\ No newline at end of file
+ lore: ""
+
+ iep:
+ material: "elytra"
+ name: "<#4800FF>Flying"
+ lore: "Parkour with elytra!"
\ No newline at end of file
diff --git a/src/main/resources/locales/nl.yml b/src/main/resources/locales/nl.yml
index f33e1044..e796954e 100644
--- a/src/main/resources/locales/nl.yml
+++ b/src/main/resources/locales/nl.yml
@@ -252,4 +252,9 @@ other:
close:
material: "arrow"
name: "<#F5A3A3>Sluiten"
- lore: ""
\ No newline at end of file
+ lore: ""
+
+ iep:
+ material: "elytra"
+ name: "<#4800FF>Vliegen"
+ lore: "Parkour met elytra!"
\ No newline at end of file
diff --git a/src/main/resources/locales/zh_cn.yml b/src/main/resources/locales/zh_cn.yml
index af6ba196..d2656f8a 100644
--- a/src/main/resources/locales/zh_cn.yml
+++ b/src/main/resources/locales/zh_cn.yml
@@ -253,3 +253,8 @@ other:
material: "arrow"
name: "<#F5A3A3>关闭"
lore: ""
+
+ iep:
+ material: "elytra"
+ name: "<#4800FF>Flying"
+ lore: "Parkour with elytra!"
\ No newline at end of file
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 352face6..bb245778 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -1,7 +1,7 @@
name: 'IP'
description: 'Infinitely automatically generating parkour plugin.'
author: Efnilite
-version: 5.2.0
+version: 5.2.1
api-version: 1.16
main: dev.efnilite.ip.IP
softdepend: [floodgate, Vault, PlaceholderAPI, Multiverse-Core, VoidGen]