mirror of
https://gitlab.com/phoenix-dvpmt/mmocore.git
synced 2024-11-30 01:13:38 +01:00
Fixed waypoint path calculation. Option to disable auto waypoint path calculation
This commit is contained in:
parent
f24a1b0a6a
commit
c4ae7bfed3
@ -9,6 +9,7 @@ import io.lumine.mythic.lib.hologram.Hologram;
|
|||||||
import io.lumine.mythic.lib.version.VEnchantment;
|
import io.lumine.mythic.lib.version.VEnchantment;
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.util.Icon;
|
import net.Indyuce.mmocore.util.Icon;
|
||||||
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.attribute.Attribute;
|
import org.bukkit.attribute.Attribute;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
@ -218,12 +219,7 @@ public class MMOCoreUtils {
|
|||||||
return object.toString();
|
return object.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Deprecated
|
||||||
* Method to get all entities surrounding a location. This method does not
|
|
||||||
* take every entity in the world but rather takes all the entities from the
|
|
||||||
* 9 chunks around the entity, so even if the location is at the border of a
|
|
||||||
* chunk (worst case border of 4 chunks), the entity will still be included
|
|
||||||
*/
|
|
||||||
public static List<Entity> getNearbyChunkEntities(Location loc) {
|
public static List<Entity> getNearbyChunkEntities(Location loc) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -301,6 +297,22 @@ public class MMOCoreUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static Location readLocation(String string) {
|
||||||
|
String[] split = string.split(" ");
|
||||||
|
|
||||||
|
World world = Bukkit.getWorld(split[0]);
|
||||||
|
Validate.notNull(world, "Could not find world with name '" + split[0] + "'");
|
||||||
|
|
||||||
|
double x = Double.parseDouble(split[1]);
|
||||||
|
double y = Double.parseDouble(split[2]);
|
||||||
|
double z = Double.parseDouble(split[3]);
|
||||||
|
float yaw = split.length > 4 ? (float) Double.parseDouble(split[4]) : 0;
|
||||||
|
float pitch = split.length > 5 ? (float) Double.parseDouble(split[5]) : 0;
|
||||||
|
|
||||||
|
return new Location(world, x, y, z, yaw, pitch);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Center location of an entity using its bounding box
|
* @return Center location of an entity using its bounding box
|
||||||
*/
|
*/
|
||||||
|
@ -13,6 +13,7 @@ import net.Indyuce.mmocore.gui.api.item.Placeholders;
|
|||||||
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
|
import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem;
|
||||||
import net.Indyuce.mmocore.waypoint.Waypoint;
|
import net.Indyuce.mmocore.waypoint.Waypoint;
|
||||||
import net.Indyuce.mmocore.waypoint.WaypointPath;
|
import net.Indyuce.mmocore.waypoint.WaypointPath;
|
||||||
|
import net.Indyuce.mmocore.waypoint.WaypointPathCalculation;
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
@ -26,7 +27,6 @@ import org.bukkit.persistence.PersistentDataType;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ public class WaypointViewer extends EditableInventory {
|
|||||||
|
|
||||||
public class WaypointItem extends SimplePlaceholderItem<WaypointViewerInventory> {
|
public class WaypointItem extends SimplePlaceholderItem<WaypointViewerInventory> {
|
||||||
private final SimplePlaceholderItem noWaypoint, locked;
|
private final SimplePlaceholderItem noWaypoint, locked;
|
||||||
private final WaypointItemHandler availWaypoint, noStellium, notLinked, notDynamic, currentWayPoint;
|
private final WaypointItemHandler availWaypoint, noStellium, notLinked, currentWayPoint;
|
||||||
|
|
||||||
public WaypointItem(ConfigurationSection config) {
|
public WaypointItem(ConfigurationSection config) {
|
||||||
super(Material.BARRIER, config);
|
super(Material.BARRIER, config);
|
||||||
@ -80,7 +80,7 @@ public class WaypointViewer extends EditableInventory {
|
|||||||
Validate.notNull(config.getConfigurationSection("no-waypoint"), "Could not load 'no-waypoint' config");
|
Validate.notNull(config.getConfigurationSection("no-waypoint"), "Could not load 'no-waypoint' config");
|
||||||
Validate.notNull(config.getConfigurationSection("locked"), "Could not load 'locked' config");
|
Validate.notNull(config.getConfigurationSection("locked"), "Could not load 'locked' config");
|
||||||
Validate.notNull(config.getConfigurationSection("not-a-destination"), "Could not load 'not-a-destination' config");
|
Validate.notNull(config.getConfigurationSection("not-a-destination"), "Could not load 'not-a-destination' config");
|
||||||
Validate.notNull(config.getConfigurationSection("not-dynamic"), "Could not load 'not-dynamic' config");
|
//Validate.notNull(config.getConfigurationSection("not-dynamic"), "Could not load 'not-dynamic' config");
|
||||||
Validate.notNull(config.getConfigurationSection("current-waypoint"), "Could not load 'current-waypoint' config");
|
Validate.notNull(config.getConfigurationSection("current-waypoint"), "Could not load 'current-waypoint' config");
|
||||||
Validate.notNull(config.getConfigurationSection("not-enough-stellium"), "Could not load 'not-enough-stellium' config");
|
Validate.notNull(config.getConfigurationSection("not-enough-stellium"), "Could not load 'not-enough-stellium' config");
|
||||||
Validate.notNull(config.getConfigurationSection("display"), "Could not load 'display' config");
|
Validate.notNull(config.getConfigurationSection("display"), "Could not load 'display' config");
|
||||||
@ -88,7 +88,7 @@ public class WaypointViewer extends EditableInventory {
|
|||||||
noWaypoint = new SimplePlaceholderItem(config.getConfigurationSection("no-waypoint"));
|
noWaypoint = new SimplePlaceholderItem(config.getConfigurationSection("no-waypoint"));
|
||||||
locked = new SimplePlaceholderItem(config.getConfigurationSection("locked"));
|
locked = new SimplePlaceholderItem(config.getConfigurationSection("locked"));
|
||||||
notLinked = new WaypointItemHandler(config.getConfigurationSection("not-a-destination"), true);
|
notLinked = new WaypointItemHandler(config.getConfigurationSection("not-a-destination"), true);
|
||||||
notDynamic = new WaypointItemHandler(config.getConfigurationSection("not-dynamic"), true);
|
//notDynamic = new WaypointItemHandler(config.getConfigurationSection("not-dynamic"), true);
|
||||||
currentWayPoint = new WaypointItemHandler(config.getConfigurationSection("current-waypoint"), true);
|
currentWayPoint = new WaypointItemHandler(config.getConfigurationSection("current-waypoint"), true);
|
||||||
noStellium = new WaypointItemHandler(config.getConfigurationSection("not-enough-stellium"), false);
|
noStellium = new WaypointItemHandler(config.getConfigurationSection("not-enough-stellium"), false);
|
||||||
availWaypoint = new WaypointItemHandler(config.getConfigurationSection("display"), false);
|
availWaypoint = new WaypointItemHandler(config.getConfigurationSection("display"), false);
|
||||||
@ -106,23 +106,21 @@ public class WaypointViewer extends EditableInventory {
|
|||||||
if (index >= inv.waypoints.size())
|
if (index >= inv.waypoints.size())
|
||||||
return noWaypoint.display(inv, n);
|
return noWaypoint.display(inv, n);
|
||||||
|
|
||||||
// Locked waypoint?
|
final Waypoint waypoint = inv.waypoints.get(index);
|
||||||
Waypoint waypoint = inv.waypoints.get(index);
|
|
||||||
|
// Current waypoint
|
||||||
if (inv.current != null && inv.current.equals(waypoint))
|
if (inv.current != null && inv.current.equals(waypoint))
|
||||||
return currentWayPoint.display(inv, n);
|
return currentWayPoint.display(inv, n);
|
||||||
|
|
||||||
|
// Locked waypoint
|
||||||
if (!inv.getPlayerData().hasWaypoint(waypoint))
|
if (!inv.getPlayerData().hasWaypoint(waypoint))
|
||||||
return locked.display(inv, n);
|
return locked.display(inv, n);
|
||||||
|
|
||||||
// Waypoints are not linked
|
// Waypoints are not linked
|
||||||
if (inv.current != null && !inv.paths.containsKey(waypoint))
|
if (!inv.paths.containsKey(waypoint))
|
||||||
return notLinked.display(inv, n);
|
return notLinked.display(inv, n);
|
||||||
|
|
||||||
// Not dynamic waypoint
|
// Normal cost
|
||||||
if (inv.current == null && !inv.paths.containsKey(waypoint))
|
|
||||||
return notDynamic.display(inv, n);
|
|
||||||
|
|
||||||
//Normal cost
|
|
||||||
if (inv.paths.get(waypoint).getCost() > inv.getPlayerData().getStellium())
|
if (inv.paths.get(waypoint).getCost() > inv.getPlayerData().getStellium())
|
||||||
return noStellium.display(inv, n);
|
return noStellium.display(inv, n);
|
||||||
|
|
||||||
@ -132,10 +130,14 @@ public class WaypointViewer extends EditableInventory {
|
|||||||
|
|
||||||
public class WaypointItemHandler extends InventoryItem<WaypointViewerInventory> {
|
public class WaypointItemHandler extends InventoryItem<WaypointViewerInventory> {
|
||||||
private final boolean onlyName;
|
private final boolean onlyName;
|
||||||
|
private final String splitter, none;
|
||||||
|
|
||||||
public WaypointItemHandler(ConfigurationSection config, boolean onlyName) {
|
public WaypointItemHandler(ConfigurationSection config, boolean onlyName) {
|
||||||
super(config);
|
super(config);
|
||||||
|
|
||||||
this.onlyName = onlyName;
|
this.onlyName = onlyName;
|
||||||
|
this.splitter = config.getString("format_path.splitter", ", ");
|
||||||
|
this.none = config.getString("format_path.none", "None");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -187,7 +189,7 @@ public class WaypointViewer extends EditableInventory {
|
|||||||
holders.register("current_cost", inv.paths.get(waypoint).getCost());
|
holders.register("current_cost", inv.paths.get(waypoint).getCost());
|
||||||
holders.register("normal_cost", decimal.format(inv.paths.containsKey(waypoint) ? inv.paths.get(waypoint).getCost() : Double.POSITIVE_INFINITY));
|
holders.register("normal_cost", decimal.format(inv.paths.containsKey(waypoint) ? inv.paths.get(waypoint).getCost() : Double.POSITIVE_INFINITY));
|
||||||
holders.register("dynamic_cost", decimal.format(waypoint.getDynamicCost()));
|
holders.register("dynamic_cost", decimal.format(waypoint.getDynamicCost()));
|
||||||
holders.register("intermediary_waypoints", inv.paths.containsKey(waypoint) ? inv.paths.get(waypoint).displayIntermediaryWayPoints(inv.isDynamicUse()) : "None");
|
holders.register("intermediary_waypoints", inv.paths.containsKey(waypoint) ? inv.paths.get(waypoint).displayIntermediaryWayPoints(splitter, none) : none);
|
||||||
}
|
}
|
||||||
|
|
||||||
return holders;
|
return holders;
|
||||||
@ -198,7 +200,8 @@ public class WaypointViewer extends EditableInventory {
|
|||||||
private final List<Waypoint> waypoints = new ArrayList<>(MMOCore.plugin.waypointManager.getAll());
|
private final List<Waypoint> waypoints = new ArrayList<>(MMOCore.plugin.waypointManager.getAll());
|
||||||
@Nullable
|
@Nullable
|
||||||
private final Waypoint current;
|
private final Waypoint current;
|
||||||
private final Map<Waypoint, WaypointPath> paths = new HashMap<>();
|
|
||||||
|
private Map<Waypoint, WaypointPath> paths;
|
||||||
|
|
||||||
private int page;
|
private int page;
|
||||||
|
|
||||||
@ -206,29 +209,7 @@ public class WaypointViewer extends EditableInventory {
|
|||||||
super(playerData, editable);
|
super(playerData, editable);
|
||||||
|
|
||||||
this.current = current;
|
this.current = current;
|
||||||
if (current != null)
|
paths = new WaypointPathCalculation(playerData).run(current).getPaths();
|
||||||
for (WaypointPath pathInfo : current.getAllPath())
|
|
||||||
paths.put(pathInfo.getFinalWaypoint(), pathInfo);
|
|
||||||
|
|
||||||
if (current == null) {
|
|
||||||
|
|
||||||
//Iterate through all the dynamic points and find all the points it is linked to and the path
|
|
||||||
HashMap<Waypoint, Double> dynamicPoints = new HashMap<>();
|
|
||||||
//We first check all the dynamic waypoints
|
|
||||||
for (Waypoint waypoint : waypoints) {
|
|
||||||
if (waypoint.mayBeUsedDynamically(playerData.getPlayer())) {
|
|
||||||
paths.put(waypoint, new WaypointPath(waypoint, waypoint.getDynamicCost()));
|
|
||||||
dynamicPoints.put(waypoint, waypoint.getDynamicCost());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (Waypoint source : dynamicPoints.keySet()) {
|
|
||||||
for (WaypointPath target : source.getAllPath()) {
|
|
||||||
if (!paths.containsKey(target.getFinalWaypoint()) || paths.get(target.getFinalWaypoint()).getCost() > target.getCost() + dynamicPoints.get(source)) {
|
|
||||||
paths.put(target.getFinalWaypoint(), target.addCost(dynamicPoints.get(source)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -259,11 +240,10 @@ public class WaypointViewer extends EditableInventory {
|
|||||||
String tag = container.has(new NamespacedKey(MMOCore.plugin, "waypointId"), PersistentDataType.STRING) ?
|
String tag = container.has(new NamespacedKey(MMOCore.plugin, "waypointId"), PersistentDataType.STRING) ?
|
||||||
container.get(new NamespacedKey(MMOCore.plugin, "waypointId"), PersistentDataType.STRING) : "";
|
container.get(new NamespacedKey(MMOCore.plugin, "waypointId"), PersistentDataType.STRING) : "";
|
||||||
|
|
||||||
if (tag.equals(""))
|
if (tag.isEmpty()) return;
|
||||||
return;
|
|
||||||
|
|
||||||
// Locked waypoint?
|
// Locked waypoint?
|
||||||
Waypoint waypoint = MMOCore.plugin.waypointManager.get(tag);
|
final Waypoint waypoint = MMOCore.plugin.waypointManager.get(tag);
|
||||||
if (!playerData.hasWaypoint(waypoint)) {
|
if (!playerData.hasWaypoint(waypoint)) {
|
||||||
ConfigMessage.fromKey("not-unlocked-waypoint").send(player);
|
ConfigMessage.fromKey("not-unlocked-waypoint").send(player);
|
||||||
return;
|
return;
|
||||||
@ -275,18 +255,12 @@ public class WaypointViewer extends EditableInventory {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Waypoint does not have target as destination
|
// No access to that waypoint
|
||||||
if (current != null && current.getPath(waypoint) == null) {
|
if (paths.get(waypoint) == null) {
|
||||||
ConfigMessage.fromKey("cannot-teleport-to").send(player);
|
ConfigMessage.fromKey("cannot-teleport-to").send(player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not dynamic waypoint
|
|
||||||
if (current == null && !paths.containsKey(waypoint)) {
|
|
||||||
ConfigMessage.fromKey("not-dynamic-waypoint").send(player);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stellium cost
|
// Stellium cost
|
||||||
double withdraw = paths.get(waypoint).getCost();
|
double withdraw = paths.get(waypoint).getCost();
|
||||||
double left = withdraw - playerData.getStellium();
|
double left = withdraw - playerData.getStellium();
|
||||||
@ -300,7 +274,6 @@ public class WaypointViewer extends EditableInventory {
|
|||||||
|
|
||||||
player.closeInventory();
|
player.closeInventory();
|
||||||
playerData.warp(waypoint, withdraw);
|
playerData.warp(waypoint, withdraw);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ public class ConfigManager {
|
|||||||
public final CommandVerbose commandVerbose = new CommandVerbose();
|
public final CommandVerbose commandVerbose = new CommandVerbose();
|
||||||
|
|
||||||
public boolean overrideVanillaExp, canCreativeCast, passiveSkillsNeedBinding, cobbleGeneratorXP, saveDefaultClassInfo, splitMainExp, splitProfessionExp, disableQuestBossBar,
|
public boolean overrideVanillaExp, canCreativeCast, passiveSkillsNeedBinding, cobbleGeneratorXP, saveDefaultClassInfo, splitMainExp, splitProfessionExp, disableQuestBossBar,
|
||||||
pvpModeEnabled, pvpModeInvulnerabilityCanDamage, forceClassSelection, enableGlobalSkillTreeGUI, enableSpecificSkillTreeGUI;
|
pvpModeEnabled, pvpModeInvulnerabilityCanDamage, forceClassSelection, enableGlobalSkillTreeGUI, enableSpecificSkillTreeGUI, waypointAutoPathCalculation;
|
||||||
public String partyChatPrefix, noSkillBoundPlaceholder;
|
public String partyChatPrefix, noSkillBoundPlaceholder;
|
||||||
public ChatColor staminaFull, staminaHalf, staminaEmpty;
|
public ChatColor staminaFull, staminaHalf, staminaEmpty;
|
||||||
public long combatLogTimer, lootChestExpireTime, lootChestPlayerCooldown, globalSkillCooldown;
|
public long combatLogTimer, lootChestExpireTime, lootChestPlayerCooldown, globalSkillCooldown;
|
||||||
@ -151,6 +151,7 @@ public class ConfigManager {
|
|||||||
disableQuestBossBar = MMOCore.plugin.getConfig().getBoolean("mmocore-quests.disable-boss-bar");
|
disableQuestBossBar = MMOCore.plugin.getConfig().getBoolean("mmocore-quests.disable-boss-bar");
|
||||||
forceClassSelection = MMOCore.plugin.getConfig().getBoolean("force-class-selection");
|
forceClassSelection = MMOCore.plugin.getConfig().getBoolean("force-class-selection");
|
||||||
waypointWarpTime = MMOCore.plugin.getConfig().getInt("waypoints.default-warp-time");
|
waypointWarpTime = MMOCore.plugin.getConfig().getInt("waypoints.default-warp-time");
|
||||||
|
waypointAutoPathCalculation = MMOCore.plugin.getConfig().getBoolean("waypoints.auto_path_calculation");
|
||||||
|
|
||||||
// Combat
|
// Combat
|
||||||
pvpModeEnabled = config.getBoolean("pvp_mode.enabled");
|
pvpModeEnabled = config.getBoolean("pvp_mode.enabled");
|
||||||
|
47
MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Pair.java
Normal file
47
MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Pair.java
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package net.Indyuce.mmocore.util;
|
||||||
|
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class Pair<L, R> {
|
||||||
|
private final L left;
|
||||||
|
private final R right;
|
||||||
|
|
||||||
|
private Pair(L left, R right) {
|
||||||
|
this.left = left;
|
||||||
|
this.right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
public L getLeft() {
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
public R getRight() {
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public String toString() {
|
||||||
|
return "(" + this.getLeft() + ',' + this.getRight() + ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static <L, R> Pair<L, R> of(L left, R right) {
|
||||||
|
return new Pair<>(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
if (this == object) return true;
|
||||||
|
if (object == null || getClass() != object.getClass()) return false;
|
||||||
|
Pair<?, ?> pair = (Pair<?, ?>) object;
|
||||||
|
return Objects.equals(left, pair.left) && Objects.equals(right, pair.right);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(left, right);
|
||||||
|
}
|
||||||
|
}
|
@ -5,17 +5,14 @@ import io.lumine.mythic.lib.util.PostLoadAction;
|
|||||||
import io.lumine.mythic.lib.util.PreloadedObject;
|
import io.lumine.mythic.lib.util.PreloadedObject;
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
|
||||||
import net.Indyuce.mmocore.loot.chest.condition.Condition;
|
import net.Indyuce.mmocore.loot.chest.condition.Condition;
|
||||||
import net.Indyuce.mmocore.loot.chest.condition.ConditionInstance;
|
import net.Indyuce.mmocore.loot.chest.condition.ConditionInstance;
|
||||||
import net.Indyuce.mmocore.player.Unlockable;
|
import net.Indyuce.mmocore.player.Unlockable;
|
||||||
import org.apache.commons.lang.Validate;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@ -59,7 +56,7 @@ public class Waypoint implements Unlockable, PreloadedObject {
|
|||||||
name = Objects.requireNonNull(config.getString("name"), "Could not load waypoint name");
|
name = Objects.requireNonNull(config.getString("name"), "Could not load waypoint name");
|
||||||
lore = Objects.requireNonNullElse(config.getStringList("lore"), new ArrayList<>());
|
lore = Objects.requireNonNullElse(config.getStringList("lore"), new ArrayList<>());
|
||||||
|
|
||||||
loc = readLocation(Objects.requireNonNull(config.getString("location"), "Could not read location"));
|
loc = MMOCoreUtils.readLocation(Objects.requireNonNull(config.getString("location"), "Could not read location"));
|
||||||
radiusSquared = Math.pow(config.getDouble("radius"), 2);
|
radiusSquared = Math.pow(config.getDouble("radius"), 2);
|
||||||
warpTime = Math.max(0, config.getInt("warp-time", MMOCore.plugin.configManager.waypointWarpTime));
|
warpTime = Math.max(0, config.getInt("warp-time", MMOCore.plugin.configManager.waypointWarpTime));
|
||||||
|
|
||||||
@ -131,75 +128,13 @@ public class Waypoint implements Unlockable, PreloadedObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Integer.POSITIVE_INFINITY if the way point is not linked
|
* @return Double.POSITIVE_INFINITY if the way point is not linked
|
||||||
* If it is, cost of the instant travel between the two waypoints.
|
* If it is, cost of the instant travel between the two waypoints.
|
||||||
*/
|
*/
|
||||||
public double getDirectCost(Waypoint waypoint) {
|
public double getDirectCost(@NotNull Waypoint waypoint) {
|
||||||
return destinations.isEmpty() ? normalCost : destinations.getOrDefault(waypoint, Double.POSITIVE_INFINITY);
|
return destinations.isEmpty() ? normalCost : destinations.getOrDefault(waypoint, Double.POSITIVE_INFINITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<WaypointPath> getAllPath() {
|
|
||||||
//All the WayPoints that have been registered
|
|
||||||
List<Waypoint> checkedPoints = new ArrayList<>();
|
|
||||||
//All the path
|
|
||||||
List<WaypointPath> paths = new ArrayList();
|
|
||||||
List<WaypointPath> pointsToCheck = new ArrayList<>();
|
|
||||||
pointsToCheck.add(new WaypointPath(this));
|
|
||||||
|
|
||||||
while (pointsToCheck.size() != 0) {
|
|
||||||
WaypointPath checked = pointsToCheck.get(0);
|
|
||||||
pointsToCheck.remove(0);
|
|
||||||
// If the point has already been checked, pass
|
|
||||||
if (checkedPoints.contains(checked.getFinalWaypoint()))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
paths.add(checked);
|
|
||||||
checkedPoints.add(checked.getFinalWaypoint());
|
|
||||||
|
|
||||||
for (Waypoint toCheck : checked.getFinalWaypoint().destinations.keySet())
|
|
||||||
if (!checkedPoints.contains(toCheck)) {
|
|
||||||
WaypointPath toCheckInfo = checked.addWayPoint(toCheck);
|
|
||||||
// We keep pointsToCheck ordered
|
|
||||||
pointsToCheck = toCheckInfo.addInOrder(pointsToCheck);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return paths;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public WaypointPath getPath(Waypoint targetWaypoint) {
|
|
||||||
//All the WayPoints that have been registered
|
|
||||||
List<Waypoint> checkedPoints = new ArrayList<>();
|
|
||||||
//All the path
|
|
||||||
List<WaypointPath> paths = new ArrayList();
|
|
||||||
List<WaypointPath> pointsToCheck = new ArrayList<>();
|
|
||||||
pointsToCheck.add(new WaypointPath(this));
|
|
||||||
|
|
||||||
while (pointsToCheck.size() != 0) {
|
|
||||||
WaypointPath checked = pointsToCheck.get(0);
|
|
||||||
pointsToCheck.remove(0);
|
|
||||||
// If the point has already been checked, pass
|
|
||||||
if (checkedPoints.contains(checked.getFinalWaypoint()))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
paths.add(checked);
|
|
||||||
checkedPoints.add(checked.getFinalWaypoint());
|
|
||||||
|
|
||||||
if (checked.getFinalWaypoint().equals(targetWaypoint))
|
|
||||||
return checked;
|
|
||||||
|
|
||||||
for (Waypoint toCheck : checked.getFinalWaypoint().destinations.keySet())
|
|
||||||
if (!checkedPoints.contains(toCheck)) {
|
|
||||||
WaypointPath toCheckInfo = checked.addWayPoint(toCheck);
|
|
||||||
// We keep pointsToCheck ordered
|
|
||||||
pointsToCheck = toCheckInfo.addInOrder(pointsToCheck);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//If no path has been found we return null
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasOption(WaypointOption option) {
|
public boolean hasOption(WaypointOption option) {
|
||||||
return options.get(option);
|
return options.get(option);
|
||||||
}
|
}
|
||||||
@ -208,6 +143,11 @@ public class Waypoint implements Unlockable, PreloadedObject {
|
|||||||
return player.getWorld().equals(loc.getWorld()) && player.getLocation().distanceSquared(loc) < radiusSquared;
|
return player.getWorld().equals(loc.getWorld()) && player.getLocation().distanceSquared(loc) < radiusSquared;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Map<Waypoint, Double> getDestinations() {
|
||||||
|
return destinations;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return id;
|
return id;
|
||||||
@ -245,19 +185,4 @@ public class Waypoint implements Unlockable, PreloadedObject {
|
|||||||
Waypoint waypoint = (Waypoint) o;
|
Waypoint waypoint = (Waypoint) o;
|
||||||
return id.equals(waypoint.id);
|
return id.equals(waypoint.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Location readLocation(String string) {
|
|
||||||
String[] split = string.split(" ");
|
|
||||||
|
|
||||||
World world = Bukkit.getWorld(split[0]);
|
|
||||||
Validate.notNull(world, "Could not find world with name '" + split[0] + "'");
|
|
||||||
|
|
||||||
double x = Double.parseDouble(split[1]);
|
|
||||||
double y = Double.parseDouble(split[2]);
|
|
||||||
double z = Double.parseDouble(split[3]);
|
|
||||||
float yaw = split.length > 4 ? (float) Double.parseDouble(split[4]) : 0;
|
|
||||||
float pitch = split.length > 5 ? (float) Double.parseDouble(split[5]) : 0;
|
|
||||||
|
|
||||||
return new Location(world, x, y, z, yaw, pitch);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,29 +1,25 @@
|
|||||||
package net.Indyuce.mmocore.waypoint;
|
package net.Indyuce.mmocore.waypoint;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class WaypointPath {
|
public class WaypointPath {
|
||||||
private final List<Waypoint> waypoints;
|
private final List<Waypoint> waypoints = new ArrayList<>();
|
||||||
private double cost;
|
private final double cost;
|
||||||
|
|
||||||
public WaypointPath(Waypoint waypoint) {
|
public static final WaypointPath INFINITE = new WaypointPath(Double.POSITIVE_INFINITY);
|
||||||
this.waypoints = new ArrayList<>();
|
|
||||||
this.waypoints.add(waypoint);
|
public WaypointPath() {
|
||||||
cost = 0;
|
this(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WaypointPath(Waypoint waypoint, double cost) {
|
public WaypointPath(double cost) {
|
||||||
this.waypoints = new ArrayList<>();
|
|
||||||
this.waypoints.add(waypoint);
|
|
||||||
this.cost = cost;
|
|
||||||
}
|
|
||||||
|
|
||||||
public WaypointPath(List<Waypoint> waypoints, double cost) {
|
|
||||||
this.waypoints = new ArrayList<>(waypoints);
|
|
||||||
this.cost = cost;
|
this.cost = cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public List<Waypoint> getWaypoints() {
|
public List<Waypoint> getWaypoints() {
|
||||||
return waypoints;
|
return waypoints;
|
||||||
}
|
}
|
||||||
@ -32,54 +28,25 @@ public class WaypointPath {
|
|||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WaypointPath addCost(double cost) {
|
@NotNull
|
||||||
this.cost += cost;
|
public String displayIntermediaryWayPoints(String splitter, String none) {
|
||||||
return this;
|
if (waypoints.isEmpty()) return none;
|
||||||
|
|
||||||
|
boolean b = false;
|
||||||
|
final StringBuilder result = new StringBuilder();
|
||||||
|
for (Waypoint waypoint : waypoints) {
|
||||||
|
if (b) result.append(splitter);
|
||||||
|
result.append(waypoint.getName());
|
||||||
|
if (!b) b = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<WaypointPath> addInOrder(List<WaypointPath> pathInfos) {
|
return result.toString();
|
||||||
int index = 0;
|
|
||||||
while (index < pathInfos.size()) {
|
|
||||||
if (cost < pathInfos.get(index).cost) {
|
|
||||||
pathInfos.set(index, this);
|
|
||||||
return pathInfos;
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
// If index == pathInfos.size() add the waypoint at the end
|
|
||||||
pathInfos.add(this);
|
|
||||||
return pathInfos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
/**
|
public WaypointPath push(@NotNull Waypoint waypoint, double extraCost) {
|
||||||
* @param dynamic Display the first waypoint if it is dynamic as it is an intermediary point
|
final WaypointPath clone = new WaypointPath(this.cost + extraCost);
|
||||||
* @return List with all
|
clone.waypoints.add(waypoint);
|
||||||
*/
|
return clone;
|
||||||
public String displayIntermediaryWayPoints(boolean dynamic) {
|
|
||||||
int beginIndex = dynamic ? 0 : 1;
|
|
||||||
if (waypoints.size() <= beginIndex + 1)
|
|
||||||
return "None";
|
|
||||||
|
|
||||||
String result = "";
|
|
||||||
for (int i = beginIndex; i < waypoints.size() - 1; i++)
|
|
||||||
result += waypoints.get(i).getName() + (i != waypoints.size() - 2 ? ", " : "");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public WaypointPath addWayPoint(Waypoint waypoint) {
|
|
||||||
List<Waypoint> newWaypoints = new ArrayList<>();
|
|
||||||
newWaypoints.addAll(waypoints);
|
|
||||||
newWaypoints.add(waypoint);
|
|
||||||
double cost = this.cost + getFinalWaypoint().getDirectCost(waypoint);
|
|
||||||
return new WaypointPath(newWaypoints, cost);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Waypoint getInitialWaypoint() {
|
|
||||||
return waypoints.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Waypoint getFinalWaypoint() {
|
|
||||||
return waypoints.get(waypoints.size() - 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,107 @@
|
|||||||
|
package net.Indyuce.mmocore.waypoint;
|
||||||
|
|
||||||
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
|
import net.Indyuce.mmocore.util.Pair;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class WaypointPathCalculation {
|
||||||
|
private final PlayerData playerData;
|
||||||
|
private final Map<Waypoint, WaypointPath> paths = new HashMap<>();
|
||||||
|
|
||||||
|
public WaypointPathCalculation(PlayerData playerData) {
|
||||||
|
this.playerData = playerData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public WaypointPathCalculation run(@Nullable Waypoint source) {
|
||||||
|
if (MMOCore.plugin.configManager.waypointAutoPathCalculation) runDijkstra(source);
|
||||||
|
else runSimple(source);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runSimple(@Nullable Waypoint source) {
|
||||||
|
|
||||||
|
// Direct adjacency
|
||||||
|
if (source != null) for (Map.Entry<Waypoint, Double> adjacent : source.getDestinations().entrySet())
|
||||||
|
replaceIfLower(adjacent.getKey(), adjacent.getValue());
|
||||||
|
|
||||||
|
// Dynamic waypoints
|
||||||
|
for (Waypoint waypoint : MMOCore.plugin.waypointManager.getAll())
|
||||||
|
if (waypoint.hasOption(WaypointOption.DYNAMIC)) replaceIfLower(waypoint, waypoint.getDynamicCost());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void replaceIfLower(@NotNull Waypoint adjacent, double cost) {
|
||||||
|
paths.compute(adjacent, (ignored, path) -> path == null || cost < path.getCost() ? new WaypointPath(cost) : path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the Dijkstra algorithm to compute the shortest paths between source and
|
||||||
|
* all available waypoints to a certain player. Paths using locked waypoints
|
||||||
|
* are not computed.
|
||||||
|
*
|
||||||
|
* @param source Source waypoint node
|
||||||
|
*/
|
||||||
|
public void runDijkstra(@Nullable Waypoint source) {
|
||||||
|
|
||||||
|
final PriorityQueue<Pair<Waypoint, Double>> queue = new PriorityQueue<>(Comparator.comparingDouble(Pair::getRight));
|
||||||
|
final Set<Waypoint> visited = new HashSet<>();
|
||||||
|
|
||||||
|
// Initialization
|
||||||
|
for (Waypoint waypoint : MMOCore.plugin.waypointManager.getAll()) // Dynamic waypoints
|
||||||
|
if (waypoint.hasOption(WaypointOption.DYNAMIC) && waypoint.mayBeUsedDynamically(playerData.getPlayer()))
|
||||||
|
init(queue, waypoint, waypoint.getDynamicCost());
|
||||||
|
if (source != null) init(queue, source, 0); // !! After dynamic waypoints !!
|
||||||
|
|
||||||
|
// Run Dijkstra
|
||||||
|
do {
|
||||||
|
final Waypoint currentNode = queue.remove().getLeft();
|
||||||
|
|
||||||
|
// Mark as visited
|
||||||
|
visited.add(currentNode);
|
||||||
|
|
||||||
|
// Iterate over neighbors
|
||||||
|
final WaypointPath nodePath = path(currentNode);
|
||||||
|
for (Map.Entry<Waypoint, Double> adjacentData : currentNode.getDestinations().entrySet()) {
|
||||||
|
|
||||||
|
// Waypoint is usable?
|
||||||
|
final Waypoint adjacentNode = adjacentData.getKey();
|
||||||
|
if (!(adjacentNode.isUnlockedByDefault()
|
||||||
|
|| adjacentNode.isOnWaypoint(playerData.getPlayer())
|
||||||
|
|| playerData.hasWaypoint(adjacentNode)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
final double edgeWeight = adjacentData.getValue();
|
||||||
|
|
||||||
|
// Update distance if necessary
|
||||||
|
final WaypointPath adjacentPath = path(adjacentNode);
|
||||||
|
if (nodePath.getCost() + edgeWeight < adjacentPath.getCost())
|
||||||
|
paths.put(adjacentNode, nodePath.push(currentNode, edgeWeight));
|
||||||
|
|
||||||
|
// Push to queue
|
||||||
|
if (!visited.contains(adjacentNode)) queue.add(Pair.of(adjacentNode, edgeWeight));
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (!queue.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(@NotNull PriorityQueue<Pair<Waypoint, Double>> queue, @NotNull Waypoint waypoint, double cost) {
|
||||||
|
queue.add(Pair.of(waypoint, cost));
|
||||||
|
paths.put(waypoint, new WaypointPath(cost));
|
||||||
|
}
|
||||||
|
|
||||||
|
private WaypointPath path(Waypoint waypoint) {
|
||||||
|
return paths.getOrDefault(waypoint, WaypointPath.INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Result of the waypoint path calculation
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public Map<Waypoint, WaypointPath> getPaths() {
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
}
|
@ -274,6 +274,18 @@ waypoints:
|
|||||||
# takes to use the waypoint and teleport to target location.
|
# takes to use the waypoint and teleport to target location.
|
||||||
default-warp-time: 100
|
default-warp-time: 100
|
||||||
|
|
||||||
|
# By default, MMOCore runs path calculation to enable players
|
||||||
|
# to take shortcuts and directly teleport across distant waypoints.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# - Player is standing at waypoint A. They want to go to waypoint C.
|
||||||
|
# - Waypoint A is linked to waypoint B, waypoint B is linked to waypoint C
|
||||||
|
# With this option toggled on, since A -> B -> C is a valid connection,
|
||||||
|
# MMOCore tells the player they can directly go to C without having to
|
||||||
|
# first teleport to B. The stellium cost is the sum of the individual
|
||||||
|
# stelium costs. MMOCore always finds the shortest path between two waypoints.
|
||||||
|
auto_path_calculation: true
|
||||||
|
|
||||||
# Change this to the name of the color you want for
|
# Change this to the name of the color you want for
|
||||||
# the different resource bar placeholders
|
# the different resource bar placeholders
|
||||||
resource-bar-colors:
|
resource-bar-colors:
|
||||||
|
@ -34,18 +34,7 @@ items:
|
|||||||
|
|
||||||
lore:
|
lore:
|
||||||
- '{lore}'
|
- '{lore}'
|
||||||
- '&7You cannot teleport as the two waypoints are not linked.'
|
- '&7You do not have access to this waypoint.'
|
||||||
|
|
||||||
|
|
||||||
# When you cannot teleport to a non dynamic waypoint
|
|
||||||
not-dynamic:
|
|
||||||
name: '&a{name}'
|
|
||||||
item: ENDER_PEARL
|
|
||||||
|
|
||||||
lore:
|
|
||||||
- '{lore}'
|
|
||||||
- '&7You cannot teleport as you are not standing on a waypoint.'
|
|
||||||
|
|
||||||
|
|
||||||
current-waypoint:
|
current-waypoint:
|
||||||
name: '&a{name}'
|
name: '&a{name}'
|
||||||
@ -53,7 +42,7 @@ items:
|
|||||||
|
|
||||||
lore:
|
lore:
|
||||||
- '{lore}'
|
- '{lore}'
|
||||||
- '&7The waypoint you are standing at.'
|
- '&7You are here.'
|
||||||
|
|
||||||
# When you don't have enough stellium
|
# When you don't have enough stellium
|
||||||
not-enough-stellium:
|
not-enough-stellium:
|
||||||
@ -69,6 +58,9 @@ items:
|
|||||||
display:
|
display:
|
||||||
name: '&a{name}'
|
name: '&a{name}'
|
||||||
item: ENDER_EYE
|
item: ENDER_EYE
|
||||||
|
path:
|
||||||
|
splitter: ', '
|
||||||
|
none: 'None'
|
||||||
lore:
|
lore:
|
||||||
- '{lore}'
|
- '{lore}'
|
||||||
- '&7You can teleport to this waypoint.'
|
- '&7You can teleport to this waypoint.'
|
||||||
|
@ -115,11 +115,10 @@ new-waypoint-book: '%&eYou unlocked the &6{waypoint} &ewaypoint!'
|
|||||||
not-enough-stellium: '&cYou don''t have enough stellium: you need {more} more.'
|
not-enough-stellium: '&cYou don''t have enough stellium: you need {more} more.'
|
||||||
waypoint-cooldown: '&cPlease wait {cooldown} before using a waypoint again.'
|
waypoint-cooldown: '&cPlease wait {cooldown} before using a waypoint again.'
|
||||||
not-unlocked-waypoint: '&cYou have not unlocked that waypoint yet.'
|
not-unlocked-waypoint: '&cYou have not unlocked that waypoint yet.'
|
||||||
not-dynamic-waypoint: '&cYou many only teleport to a non-dynamic waypoint while standing on another waypoint.'
|
|
||||||
standing-on-waypoint: '&cYou are already standing on this waypoint.'
|
standing-on-waypoint: '&cYou are already standing on this waypoint.'
|
||||||
warping-canceled: '%&cWaypoint warping canceled.'
|
warping-canceled: '%&cWaypoint warping canceled.'
|
||||||
warping-comencing: '%&cDO NOT MOVE!&e You will be warped in {left}sec.'
|
warping-comencing: '%&cDO NOT MOVE!&e You will be teleported in {left}sec.'
|
||||||
cannot-teleport-to: '&cThe two waypoints are not linked.'
|
cannot-teleport-to: '&cYou do not have access to this waypoint.'
|
||||||
|
|
||||||
# Cash
|
# Cash
|
||||||
deposit: '&eYou successfully deposited &6{worth}g&e.'
|
deposit: '&eYou successfully deposited &6{worth}g&e.'
|
||||||
|
Loading…
Reference in New Issue
Block a user