diff --git a/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/GameRule.java b/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/GameRule.java index b7fd8840..3fb0abce 100644 --- a/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/GameRule.java +++ b/api/src/main/java/de/erethon/dungeonsxl/api/dungeon/GameRule.java @@ -61,6 +61,14 @@ public class GameRule { * Shall players lose their items when they die (do not mix up this with "onEscape"!)? */ public static final GameRule KEEP_INVENTORY_ON_DEATH = new GameRule<>(Boolean.class, "keepInventoryOnDeath", true); + /** + * The location where the players spawn when they leave the dungeon without succeeding. + */ + public static final GameRule ESCAPE_LOCATION = new GameRule<>(String.class, "escapeLocation", null); + /** + * The location where the players spawn when they finish the dungeon. + */ + public static final GameRule FINISH_LOCATION = new GameRule<>(String.class, "finishLocation", null); /** * If the Lobby is disabled. This applies only to Dungeons that have to be solved alone and where there are no classes to choose from. */ diff --git a/api/src/main/java/de/erethon/dungeonsxl/api/player/GlobalPlayer.java b/api/src/main/java/de/erethon/dungeonsxl/api/player/GlobalPlayer.java index 34b1380d..6b6d9600 100644 --- a/api/src/main/java/de/erethon/dungeonsxl/api/player/GlobalPlayer.java +++ b/api/src/main/java/de/erethon/dungeonsxl/api/player/GlobalPlayer.java @@ -124,14 +124,14 @@ public interface GlobalPlayer extends PlayerWrapper { } /** - * Respawns the player at his old position before he was in a dungeon. + * Respawns the player at the location defined by the game rules or his old position before he was in a dungeon. * - * @param keepInventory if the saved status shall be reset + * @param gameFinished if the game was finished */ - void reset(boolean keepInventory); + void reset(boolean gameFinished); /** - * Respawns the player at his old position before he was in a dungeon. + * Respawns the player at the given location. * * @param tpLoc the location where the player shall respawn * @param keepInventory if the saved status shall be reset diff --git a/core/src/main/java/de/erethon/dungeonsxl/player/DGamePlayer.java b/core/src/main/java/de/erethon/dungeonsxl/player/DGamePlayer.java index 25e48551..53f0cb1a 100644 --- a/core/src/main/java/de/erethon/dungeonsxl/player/DGamePlayer.java +++ b/core/src/main/java/de/erethon/dungeonsxl/player/DGamePlayer.java @@ -371,11 +371,7 @@ public class DGamePlayer extends DInstancePlayer implements GamePlayer { delete(); if (player.isOnline()) { - if (finished) { - reset(rules.getState(GameRule.KEEP_INVENTORY_ON_FINISH)); - } else { - reset(rules.getState(GameRule.KEEP_INVENTORY_ON_ESCAPE)); - } + reset(finished); } // Permission bridge diff --git a/core/src/main/java/de/erethon/dungeonsxl/player/DGlobalPlayer.java b/core/src/main/java/de/erethon/dungeonsxl/player/DGlobalPlayer.java index 927d0ca4..ed51a4b3 100644 --- a/core/src/main/java/de/erethon/dungeonsxl/player/DGlobalPlayer.java +++ b/core/src/main/java/de/erethon/dungeonsxl/player/DGlobalPlayer.java @@ -33,6 +33,7 @@ import de.erethon.dungeonsxl.config.DMessage; import de.erethon.dungeonsxl.dungeon.DGame; import de.erethon.dungeonsxl.event.dgroup.DGroupCreateEvent; import de.erethon.dungeonsxl.global.DPortal; +import de.erethon.dungeonsxl.util.LocationString; import de.erethon.dungeonsxl.util.NBTUtil; import java.io.File; import java.util.ArrayList; @@ -415,8 +416,33 @@ public class DGlobalPlayer implements GlobalPlayer { } @Override - public void reset(boolean keepInventory) { - final Location tpLoc = data.getOldLocation().getWorld() != null ? data.getOldLocation() : Bukkit.getWorlds().get(0).getSpawnLocation(); + public void reset(boolean gameFinished) { + Location tpLoc; + boolean keepInventory; + if (getGroup() != null) { + Dungeon dungeon = getGroup().getDungeon(); + GameRuleContainer rules = dungeon.getRules(); + keepInventory = rules.getState(gameFinished ? GameRule.KEEP_INVENTORY_ON_FINISH : GameRule.KEEP_INVENTORY_ON_ESCAPE); + LocationString tpLocString = LocationString.fromString(rules.getState(gameFinished ? GameRule.FINISH_LOCATION : GameRule.ESCAPE_LOCATION)); + if (tpLocString != null && tpLocString.getLocation() != null) { + tpLoc = tpLocString.getLocation(); + } else { + if (data.getOldLocation().getWorld() != null) { + tpLoc = data.getOldLocation(); + } else { + tpLoc = Bukkit.getWorlds().get(0).getSpawnLocation(); + } + } + + } else { + if (data.getOldLocation().getWorld() != null) { + tpLoc = data.getOldLocation(); + } else { + tpLoc = Bukkit.getWorlds().get(0).getSpawnLocation(); + } + keepInventory = false; + } + if (player.isDead()) { new BukkitRunnable() { @Override diff --git a/core/src/main/java/de/erethon/dungeonsxl/player/DPlayerListener.java b/core/src/main/java/de/erethon/dungeonsxl/player/DPlayerListener.java index ff75046f..2dd9ab5d 100644 --- a/core/src/main/java/de/erethon/dungeonsxl/player/DPlayerListener.java +++ b/core/src/main/java/de/erethon/dungeonsxl/player/DPlayerListener.java @@ -38,6 +38,7 @@ import de.erethon.dungeonsxl.util.ParsingUtil; import de.erethon.dungeonsxl.world.DGameWorld; import de.erethon.dungeonsxl.world.block.LockedDoor; import java.util.ArrayList; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.World; @@ -388,7 +389,8 @@ public class DPlayerListener implements Listener { DGlobalPlayer dPlayer = new DGlobalPlayer(plugin, player); if (dPlayer.getData().wasInGame()) { - dPlayer.reset(dPlayer.getData().getKeepInventoryAfterLogout()); + dPlayer.reset(dPlayer.getData().getOldLocation() != null ? dPlayer.getData().getOldLocation() : Bukkit.getWorlds().get(0).getSpawnLocation(), + dPlayer.getData().getKeepInventoryAfterLogout()); } if (!dPlayer.getData().hasFinishedTutorial() && config.isTutorialActivated()) { diff --git a/core/src/main/java/de/erethon/dungeonsxl/util/LocationString.java b/core/src/main/java/de/erethon/dungeonsxl/util/LocationString.java new file mode 100644 index 00000000..37738f92 --- /dev/null +++ b/core/src/main/java/de/erethon/dungeonsxl/util/LocationString.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2012-2020 Frank Baumann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package de.erethon.dungeonsxl.util; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; + +/** + * @author Daniel Saukel + */ +public class LocationString { + + private String raw; + private String world; + private double x, y, z; + private float yaw, pitch; + private Location location; + + private LocationString(String string) { + raw = string; + } + + public static LocationString fromString(String string) { + if (string == null) { + return null; + } + + String[] args = string.split(","); + if (args.length < 4 || args.length == 5 || args.length > 6) { + return null; + } + + double x, y, z; + float yaw, pitch; + try { + x = Double.parseDouble(args[1]); + y = Double.parseDouble(args[2]); + z = Double.parseDouble(args[3]); + if (args.length == 6) { + yaw = Float.parseFloat(args[4]); + pitch = Float.parseFloat(args[5]); + } else { + yaw = 0f; + pitch = 0f; + } + } catch (NumberFormatException exception) { + return null; + } + + LocationString locationString = new LocationString(string); + locationString.world = args[0]; + locationString.x = x; + locationString.y = y; + locationString.z = z; + locationString.yaw = yaw; + locationString.pitch = pitch; + return locationString; + } + + public Location getLocation() { + if (location == null) { + World bukkitWorld = Bukkit.getWorld(world); + if (bukkitWorld == null) { + return null; + } + location = new Location(bukkitWorld, x, y, z, yaw, pitch); + } + return location; + } + + @Override + public String toString() { + return raw; + } + +}