diff --git a/src/main/java/net/knarcraft/stargate/command/CommandConfig.java b/src/main/java/net/knarcraft/stargate/command/CommandConfig.java index 0f6dccb..ca2f2fa 100644 --- a/src/main/java/net/knarcraft/stargate/command/CommandConfig.java +++ b/src/main/java/net/knarcraft/stargate/command/CommandConfig.java @@ -90,6 +90,15 @@ public class CommandConfig implements CommandExecutor { configuration.set(selectedOption.getConfigNode(), intValue); } } + case DOUBLE -> { + Double doubleValue = getDouble(commandSender, selectedOption, value); + if (doubleValue == null) { + return; + } else { + Stargate.getStargateConfig().getConfigOptionsReference().put(selectedOption, doubleValue); + configuration.set(selectedOption.getConfigNode(), doubleValue); + } + } case STRING -> { updateStringConfigValue(selectedOption, commandSender, value); configuration.set(selectedOption.getConfigNode(), value); @@ -314,6 +323,30 @@ public class CommandConfig implements CommandExecutor { } } + /** + * Gets a double from a string + * + * @param commandSender

The command sender that sent the config command

+ * @param selectedOption

The option the command sender is trying to change

+ * @param value

The value given

+ * @return

A double, or null if it was invalid

+ */ + private Double getDouble(CommandSender commandSender, ConfigOption selectedOption, String value) { + try { + double doubleValue = Double.parseDouble(value); + + if (selectedOption == ConfigOption.EXIT_VELOCITY && doubleValue < 0) { + commandSender.sendMessage(ChatColor.RED + "This config option cannot be negative."); + return null; + } + + return doubleValue; + } catch (NumberFormatException exception) { + commandSender.sendMessage(ChatColor.RED + "Invalid number given"); + return null; + } + } + /** * Reloads the config if necessary * diff --git a/src/main/java/net/knarcraft/stargate/command/ConfigTabCompleter.java b/src/main/java/net/knarcraft/stargate/command/ConfigTabCompleter.java index c37de81..693fc26 100644 --- a/src/main/java/net/knarcraft/stargate/command/ConfigTabCompleter.java +++ b/src/main/java/net/knarcraft/stargate/command/ConfigTabCompleter.java @@ -21,16 +21,17 @@ public class ConfigTabCompleter implements TabCompleter { private List signTypes; private List booleans; - private List numbers; + private List integers; private List chatColors; private List languages; private List extendedColors; + private List doubles; @Nullable @Override public List onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] args) { - if (signTypes == null || booleans == null || numbers == null || chatColors == null || languages == null) { + if (signTypes == null || booleans == null || integers == null || chatColors == null || languages == null) { initializeAutoCompleteLists(); } if (args.length > 1) { @@ -104,7 +105,16 @@ public class ConfigTabCompleter implements TabCompleter { //If the config value is an integer, display some valid numbers if (selectedOption.getDataType() == OptionDataType.INTEGER) { if (typedText.trim().isEmpty()) { - return numbers; + return integers; + } else { + return new ArrayList<>(); + } + } + + //If the config value is a double, display some valid numbers + if (selectedOption.getDataType() == OptionDataType.DOUBLE) { + if (typedText.trim().isEmpty()) { + return doubles; } else { return new ArrayList<>(); } @@ -164,9 +174,9 @@ public class ConfigTabCompleter implements TabCompleter { booleans.add("true"); booleans.add("false"); - numbers = new ArrayList<>(); - numbers.add("0"); - numbers.add("5"); + integers = new ArrayList<>(); + integers.add("0"); + integers.add("5"); signTypes = new ArrayList<>(); for (Material material : Material.values()) { @@ -181,6 +191,12 @@ public class ConfigTabCompleter implements TabCompleter { extendedColors = new ArrayList<>(chatColors); extendedColors.add("default"); extendedColors.add("inverted"); + + doubles = new ArrayList<>(); + doubles.add("5"); + doubles.add("1"); + doubles.add("0.5"); + doubles.add("0.1"); } diff --git a/src/main/java/net/knarcraft/stargate/config/ConfigOption.java b/src/main/java/net/knarcraft/stargate/config/ConfigOption.java index 76d3870..2169d14 100644 --- a/src/main/java/net/knarcraft/stargate/config/ConfigOption.java +++ b/src/main/java/net/knarcraft/stargate/config/ConfigOption.java @@ -156,8 +156,12 @@ public enum ConfigOption { /** * Whether to alert admins about new updates */ - ADMIN_UPDATE_ALERT("adminUpdateAlert", "Whether to alert admins about new plugin updates", true); + ADMIN_UPDATE_ALERT("adminUpdateAlert", "Whether to alert admins about new plugin updates", true), + /** + * The velocity of players exiting a stargate, relative to the entry velocity + */ + EXIT_VELOCITY("gates.exitVelocity", "The velocity of players exiting stargates, relative to the entry velocity", 0.1D); private final String configNode; private final String description; @@ -184,6 +188,8 @@ public enum ConfigOption { this.dataType = OptionDataType.BOOLEAN; } else if (defaultValue instanceof Integer) { this.dataType = OptionDataType.INTEGER; + } else if (defaultValue instanceof Double) { + this.dataType = OptionDataType.DOUBLE; } else { throw new IllegalArgumentException("Unknown config data type encountered: " + defaultValue); } diff --git a/src/main/java/net/knarcraft/stargate/config/OptionDataType.java b/src/main/java/net/knarcraft/stargate/config/OptionDataType.java index 5cb8bee..25fcf76 100644 --- a/src/main/java/net/knarcraft/stargate/config/OptionDataType.java +++ b/src/main/java/net/knarcraft/stargate/config/OptionDataType.java @@ -6,17 +6,28 @@ package net.knarcraft.stargate.config; public enum OptionDataType { /** - * The data type for the option is a String + * The data type if the option is a String */ STRING, + /** - * The data type for the option is a Boolean + * The data type if the option is a Boolean */ BOOLEAN, - STRING_LIST, + /** - * The data type for the option is an Integer + * The data type if the option is a string list */ - INTEGER + STRING_LIST, + + /** + * The data type if the option is an Integer + */ + INTEGER, + + /** + * The data type if the option is a double + */ + DOUBLE } diff --git a/src/main/java/net/knarcraft/stargate/config/StargateConfig.java b/src/main/java/net/knarcraft/stargate/config/StargateConfig.java index 346bb4d..d8acd65 100644 --- a/src/main/java/net/knarcraft/stargate/config/StargateConfig.java +++ b/src/main/java/net/knarcraft/stargate/config/StargateConfig.java @@ -358,6 +358,7 @@ public final class StargateConfig { } case BOOLEAN -> optionValue = newConfig.getBoolean(configNode); case INTEGER -> optionValue = newConfig.getInt(configNode); + case DOUBLE -> optionValue = newConfig.getDouble(configNode); default -> throw new IllegalArgumentException("Invalid config data type encountered"); } configOptions.put(option, optionValue); diff --git a/src/main/java/net/knarcraft/stargate/config/StargateGateConfig.java b/src/main/java/net/knarcraft/stargate/config/StargateGateConfig.java index 001ced9..1e19865 100644 --- a/src/main/java/net/knarcraft/stargate/config/StargateGateConfig.java +++ b/src/main/java/net/knarcraft/stargate/config/StargateGateConfig.java @@ -179,6 +179,15 @@ public final class StargateGateConfig { return (String) configOptions.get(ConfigOption.DEFAULT_GATE_NETWORK); } + /** + * Gets the exit velocity of players using stargates, relative to the entry velocity + * + * @return

The relative exit velocity

+ */ + public double getExitVelocity() { + return (double) configOptions.get(ConfigOption.EXIT_VELOCITY); + } + /** * Loads all config values related to gates */ diff --git a/src/main/java/net/knarcraft/stargate/portal/teleporter/PlayerTeleporter.java b/src/main/java/net/knarcraft/stargate/portal/teleporter/PlayerTeleporter.java index e8232bb..57d6e6d 100644 --- a/src/main/java/net/knarcraft/stargate/portal/teleporter/PlayerTeleporter.java +++ b/src/main/java/net/knarcraft/stargate/portal/teleporter/PlayerTeleporter.java @@ -3,9 +3,12 @@ package net.knarcraft.stargate.portal.teleporter; import net.knarcraft.stargate.Stargate; import net.knarcraft.stargate.event.StargatePlayerPortalEvent; import net.knarcraft.stargate.portal.Portal; +import net.knarcraft.stargate.utility.DirectionHelper; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.util.Vector; /** * The portal teleporter takes care of the actual portal teleportation for any players @@ -32,6 +35,7 @@ public class PlayerTeleporter extends Teleporter { * @param event

The player move event triggering the event

*/ public void teleport(Portal origin, PlayerMoveEvent event) { + double velocity = player.getVelocity().length(); Location traveller = player.getLocation(); Location exit = getExit(player, traveller); @@ -56,9 +60,16 @@ public class PlayerTeleporter extends Teleporter { if (event == null) { player.teleport(exit); } else { - //The new method to teleport in a move event is set the "to" field. + //Set the exit location of the event event.setTo(exit); } + + //Set the velocity of the teleported player after the teleportation is finished + Bukkit.getScheduler().scheduleSyncDelayedTask(Stargate.getInstance(), () -> { + Vector newVelocityDirection = DirectionHelper.getDirectionVectorFromYaw(portal.getYaw()); + Vector newVelocity = newVelocityDirection.multiply(velocity * Stargate.getGateConfig().getExitVelocity()); + player.setVelocity(newVelocity); + }, 1); } /** diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 46d18d2..9775000 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -15,6 +15,8 @@ gates: maxGatesEachNetwork: 0 # defaultGateNetwork - The default gate network defaultGateNetwork: central + # exitVelocity - The velocity of players exiting stargates, relative to the entry velocity + exitVelocity: 0.1 cosmetic: # rememberDestination - Whether to remember the cursor location between uses rememberDestination: false