From 761ed2a1b4e8d38477f8dc3506515aef7d94d64e Mon Sep 17 00:00:00 2001 From: Spazzinq <26337405+Spazzinq@users.noreply.github.com> Date: Thu, 8 Aug 2019 11:56:46 -0400 Subject: [PATCH] Timed temp bypass flight, bug fixes (3.4) --- FlightControl/pom.xml | 24 ++-- .../spazzinq/flightcontrol/ConfigManager.java | 57 ++------ .../spazzinq/flightcontrol/FlightControl.java | 70 +++++----- .../spazzinq/flightcontrol/FlightManager.java | 7 +- .../org/spazzinq/flightcontrol/Listener.java | 15 ++- .../flightcontrol/TempFlyManager.java | 127 ++++++++++++++++++ .../spazzinq/flightcontrol/TrailManager.java | 73 +++++++++- .../org/spazzinq/flightcontrol/Updater.java | 5 +- .../commands/FlightControlCommand.java | 12 +- .../flightcontrol/commands/FlyCommand.java | 29 ++-- .../commands/TempFlyCommand.java | 101 ++++++++++---- .../commands/ToggleTrailCommand.java | 62 +++++++++ .../flightcontrol/utils/Actionbar.java | 82 +++++++++++ FlightControl/src/main/resources/config.yml | 2 +- FlightControl/src/main/resources/plugin.yml | 1 + pom.xml | 2 +- 16 files changed, 523 insertions(+), 146 deletions(-) create mode 100644 FlightControl/src/main/java/org/spazzinq/flightcontrol/TempFlyManager.java create mode 100644 FlightControl/src/main/java/org/spazzinq/flightcontrol/commands/ToggleTrailCommand.java create mode 100644 FlightControl/src/main/java/org/spazzinq/flightcontrol/utils/Actionbar.java diff --git a/FlightControl/pom.xml b/FlightControl/pom.xml index 57b2fffb..7f99c68f 100644 --- a/FlightControl/pom.xml +++ b/FlightControl/pom.xml @@ -100,6 +100,10 @@ spazz-repo https://mvn.spazzinq.org/repository/ + + CodeMC + https://repo.codemc.org/repository/maven-public/ + spigotmc-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots/ @@ -108,10 +112,6 @@ sk89q-repo https://maven.sk89q.com/repo/ - - CodeMC - https://repo.codemc.org/repository/maven-public/ - ess-facs-repo https://ci.ender.zone/plugin/repository/everything/ @@ -119,10 +119,16 @@ + + org.bstats + bstats-bukkit + 1.5 + compile + org.spigotmc spigot-api - 1.8.8-R0.1-SNAPSHOT + 1.14.4-R0.1-SNAPSHOT provided @@ -146,7 +152,7 @@ net.ess3 EssentialsX - 2.17.0 + 2.17.1 provided @@ -391,11 +397,5 @@ lombok 1.18.8 - - org.bstats - bstats-bukkit - 1.5 - compile - \ No newline at end of file diff --git a/FlightControl/src/main/java/org/spazzinq/flightcontrol/ConfigManager.java b/FlightControl/src/main/java/org/spazzinq/flightcontrol/ConfigManager.java index a683d11b..2788ab2e 100644 --- a/FlightControl/src/main/java/org/spazzinq/flightcontrol/ConfigManager.java +++ b/FlightControl/src/main/java/org/spazzinq/flightcontrol/ConfigManager.java @@ -29,8 +29,6 @@ import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.permissions.Permission; import org.bukkit.permissions.PermissionDefault; import org.bukkit.plugin.PluginManager; @@ -45,11 +43,9 @@ public final class ConfigManager { private FlightControl pl; private PluginManager pm; - CommentedConfig configData; + CommentedConfig configData; private File f; - private File trailFile; - private FileConfiguration trailConfig; @Getter @Setter boolean autoEnable, autoUpdate, support, @@ -60,29 +56,25 @@ public final class ConfigManager { @Getter @Setter double facEnemyRange; @Getter @Setter float flightSpeed; - String dFlight, eFlight, cFlight, nFlight, - dTrail, eTrail; + @Getter + String dFlight, eFlight, cFlight, nFlight, disableTrail, enableTrail; @Getter String noPermission; Sound eSound, dSound, cSound, nSound; HashSet worlds; - HashSet trailPrefs; HashMap> regions; HashMap categories; ConfigManager(FlightControl pl) { this.pl = pl; pm = pl.getServer().getPluginManager(); - trailFile = new File(pl.getDataFolder(), "disabled_trail.yml"); f = new File(pl.getDataFolder(), "config.yml"); reloadConfig(); updateConfig(); } - public void reloadConfig() { - if (trailPrefs != null) saveTrailPrefs(); - + void reloadConfig() { pl.saveDefaultConfig(); try { configData = new CommentedConfig(f, pl.getResource("config.yml")); @@ -115,18 +107,18 @@ public void reloadConfig() { eFlight = configData.getString("messages.flight.enable"); cFlight = configData.getString("messages.flight.can_enable"); nFlight = configData.getString("messages.flight.cannot_enable"); - dTrail = configData.getString("messages.trail.disable"); - eTrail = configData.getString("messages.trail.enable"); + disableTrail = configData.getString("messages.trail.disable"); + enableTrail = configData.getString("messages.trail.enable"); noPermission = configData.getString("messages.permission_denied"); // Load other stuff that have separate methods loadWorlds(); loadSounds(); loadTrail(); - loadTrailPrefs(); + // Reassign it anyways because it'll cause an NPE + regions = new HashMap<>(); if (pm.isPluginEnabled("WorldGuard")) { - regions = new HashMap<>(); loadRegions(); } if (pm.isPluginEnabled("Factions")) loadCategories(); @@ -227,28 +219,6 @@ private void loadTrail() { } } - // Per-player trail preferences - private void loadTrailPrefs() { - trailPrefs = new HashSet<>(); - if (!trailFile.exists()) { - try { //noinspection ResultOfMethodCallIgnored - trailFile.createNewFile(); - } catch (IOException e) { e.printStackTrace(); } - } - trailConfig = YamlConfiguration.loadConfiguration(trailFile); - - if (trailConfig.isList("disabled_trail")) { - if (!trailConfig.getStringList("disabled_trail").isEmpty()) { - for (String uuid : trailConfig.getStringList("disabled_trail")) { - try { - if (uuid.matches("[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}")) - trailPrefs.add(UUID.fromString(uuid)); - } catch (IllegalArgumentException ignored) {} - } - } - } else trailConfig.createSection("disabled_trail"); - } - private void loadSounds() { everyEnable = configData.getBoolean("sounds.every_enable"); eSound = getSound("sounds.enable"); @@ -301,17 +271,6 @@ private Category createCategory(List types, boolean blacklist) { } // FILE CONFIG METHODS - void saveTrailPrefs() { // Saves personal trail preferences - if (trailConfig != null && trailFile != null) { - List prefs = new ArrayList<>(); - for (UUID uuid : trailPrefs) { - prefs.add(uuid.toString()); - } - trailConfig.set("disabled_trail", prefs); - try { trailConfig.save(trailFile); } catch (IOException e) { e.printStackTrace(); } - } - } - public void set(String path, Object value) { configData.set(path, value); save(); diff --git a/FlightControl/src/main/java/org/spazzinq/flightcontrol/FlightControl.java b/FlightControl/src/main/java/org/spazzinq/flightcontrol/FlightControl.java index cdff64b4..9f3bfb8d 100644 --- a/FlightControl/src/main/java/org/spazzinq/flightcontrol/FlightControl.java +++ b/FlightControl/src/main/java/org/spazzinq/flightcontrol/FlightControl.java @@ -44,6 +44,7 @@ import org.spazzinq.flightcontrol.commands.FlightControlCommand; import org.spazzinq.flightcontrol.commands.FlyCommand; import org.spazzinq.flightcontrol.commands.TempFlyCommand; +import org.spazzinq.flightcontrol.commands.ToggleTrailCommand; import org.spazzinq.flightcontrol.hooks.combat.*; import org.spazzinq.flightcontrol.hooks.factions.Factions; import org.spazzinq.flightcontrol.hooks.factions.Massive; @@ -64,15 +65,22 @@ import org.spazzinq.flightcontrol.multiversion.v1_8.WorldGuard6; import org.spazzinq.flightcontrol.objects.Category; import org.spazzinq.flightcontrol.objects.Evaluation; +import org.spazzinq.flightcontrol.utils.Actionbar; -import java.util.*; +import java.io.File; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; public final class FlightControl extends org.bukkit.plugin.java.JavaPlugin { @Getter private APIManager apiManager = APIManager.getInstance(); private PluginManager pm = Bukkit.getPluginManager(); + @Getter File storageFolder = new File(getDataFolder() + File.separator + "data"); @Getter ConfigManager configManager; @Getter FlightManager flightManager; + @Getter TempFlyManager tempflyManager; @Getter TrailManager trailManager; @Getter Updater updater; @Getter private TempFlyCommand tempFlyCommand; @@ -88,26 +96,9 @@ public final class FlightControl extends org.bukkit.plugin.java.JavaPlugin { private HashSet registeredPerms = new HashSet<>(); public void onEnable() { - getCommand("flightcontrol").setExecutor(new FlightControlCommand(this)); - // Anonymous command class - getCommand("toggletrail").setExecutor((s, cmd, label, args) -> { - if (s instanceof Player) { - Player p = (Player) s; - UUID uuid = p.getUniqueId(); - if (configManager.trailPrefs.contains(uuid)) { - configManager.trailPrefs.remove(uuid); - // No need to check for trail enable because of command listener - msg(s, configManager.eTrail, configManager.byActionBar); - } - else { - configManager.trailPrefs.add(uuid); - trailManager.trailRemove(p); - msg(s, configManager.dTrail, configManager.byActionBar); - } - } - else getLogger().info("Only players can use this command (the console isn't a player!)"); - return true; - }); + // Prepare storage folder + //noinspection ResultOfMethodCallIgnored + storageFolder.mkdirs(); boolean is1_13 = getServer().getBukkitVersion().contains("1.13") || getServer().getBukkitVersion().contains("1.14"); @@ -128,18 +119,25 @@ public void onEnable() { if (pm.isPluginEnabled("Towny")) towny = new Towny(); // Load classes + // Load FlightManager before all because Config uses it & only needs to initialize pl flightManager = new FlightManager(this); configManager = new ConfigManager(this); // Loads from Config trailManager = new TrailManager(this); + // Loads from FlightManager + tempflyManager = new TempFlyManager(this); + new Actionbar(); new Listener(this); updater = new Updater(getDescription().getVersion()); + // Load commands tempFlyCommand = new TempFlyCommand(this); getCommand("tempfly").setExecutor(tempFlyCommand); getCommand("fly").setExecutor(new FlyCommand(this)); + getCommand("flightcontrol").setExecutor(new FlightControlCommand(this)); + getCommand("toggletrail").setExecutor(new ToggleTrailCommand(this)); if (configManager.autoUpdate) updater.install(Bukkit.getConsoleSender(), true); else if (updater.exists()) new BukkitRunnable() { @@ -154,18 +152,25 @@ public void run() { } public void onDisable() { - if (configManager != null) { - configManager.saveTrailPrefs(); + if (trailManager != null) { + trailManager.saveTrailPrefs(); } } + public void reload() { + configManager.reloadConfig(); + trailManager.saveTrailPrefs(); + trailManager.reloadTrailPrefs(); + tempflyManager.reloadTempflyData(); + checkCurrentPlayers(); + } + // Set for players already online - public void checkCurrentPlayers() { - float actualSpeed = calcActualSpeed(configManager.flightSpeed); + private void checkCurrentPlayers() { for (Player p : Bukkit.getOnlinePlayers()) { flightManager.check(p); trailManager.trailCheck(p); - p.setFlySpeed(actualSpeed); + p.setFlySpeed(configManager.flightSpeed); } } @@ -173,8 +178,11 @@ Evaluation eval(Player p, Location l) { String world = l.getWorld().getName(), region = worldGuard.getRegion(l); Evaluation categories = evalCategories(p), - worlds = new Evaluation(configManager.worldBL, configManager.worlds.contains(world)), - regions = new Evaluation(configManager.regionBL, configManager.regions.containsKey(world) && configManager.regions.get(world).contains(region)); + worlds = new Evaluation(configManager.worldBL, + configManager.worlds.contains(world)), + regions = new Evaluation(configManager.regionBL, + configManager.regions.containsKey(world) + && configManager.regions.get(world).contains(region)); if (region != null) defaultPerms(world + "." + region); // Register new regions dynamically @@ -202,14 +210,14 @@ Evaluation eval(Player p, Location l) { // Distance is calculated a second time to match the shape of the other distance calculation // (this would be a cube while the other would be a sphere otherwise) if (fac.isEnemy(p, otherP) && l.distance(otherP.getLocation()) <= configManager.facEnemyRange) { - if (otherP.isFlying()) flightManager.disableFlight(otherP, false); + if (otherP.isFlying()) flightManager.check(otherP); disable = true; } } } else { for (Player otherP : worldPlayers) if (fac.isEnemy(p, otherP) && l.distance(otherP.getLocation()) <= configManager.facEnemyRange) { - if (otherP.isFlying()) flightManager.disableFlight(otherP, false); + if (otherP.isFlying()) flightManager.check(otherP); disable = true; } } @@ -271,7 +279,7 @@ private ArrayList categories(Player p) { } public static void msg(CommandSender s, String msg) { msg(s, msg, false); } - static void msg(CommandSender s, String msg, boolean actionBar) { + public static void msg(CommandSender s, String msg, boolean actionBar) { if (msg != null && !msg.isEmpty()) { String finalMsg = msg; diff --git a/FlightControl/src/main/java/org/spazzinq/flightcontrol/FlightManager.java b/FlightControl/src/main/java/org/spazzinq/flightcontrol/FlightManager.java index 8412a1b9..bf7b4c98 100644 --- a/FlightControl/src/main/java/org/spazzinq/flightcontrol/FlightManager.java +++ b/FlightControl/src/main/java/org/spazzinq/flightcontrol/FlightManager.java @@ -106,6 +106,7 @@ private void enableFlight(Player p, boolean isCommand) { pl.getApiManager().callEvent(e); if (!e.isCancelled()) { + if (isCommand) disabledByPlayerList.remove(p); p.setAllowFlight(true); if (!pl.configManager.everyEnable) Sound.play(p, pl.configManager.eSound); FlightControl.msg(p, e.getMessage(), e.isByActionbar()); @@ -116,7 +117,11 @@ public void disableFlight(Player p, boolean isCommand) { pl.getApiManager().callEvent(e); if (!e.isCancelled()) { - alreadyCanMsgList.remove(p); + if (isCommand) { + disabledByPlayerList.add(p); + alreadyCanMsgList.add(p); + } else alreadyCanMsgList.remove(p); + if (pl.configManager.fallCancelled && p.isFlying()) { cancelFallList.add(p); new BukkitRunnable() { public void run() { cancelFallList.remove(p); } }.runTaskLater(pl, 300); diff --git a/FlightControl/src/main/java/org/spazzinq/flightcontrol/Listener.java b/FlightControl/src/main/java/org/spazzinq/flightcontrol/Listener.java index b3bf1829..8a285c2f 100644 --- a/FlightControl/src/main/java/org/spazzinq/flightcontrol/Listener.java +++ b/FlightControl/src/main/java/org/spazzinq/flightcontrol/Listener.java @@ -61,8 +61,19 @@ private void onMove(PlayerMoveEvent e) { @EventHandler private void onTP(PlayerTeleportEvent e) { pl.flightManager.check(e.getPlayer(), e.getTo()); } @EventHandler private void onQuit(PlayerQuitEvent e) { pl.trailManager.trailRemove(e.getPlayer()); } @EventHandler private void onJoin(PlayerJoinEvent e) { - Player p = e.getPlayer(); pl.flightManager.check(p); - if (p.isFlying()) new BukkitRunnable() { public void run() { pl.trailManager.trailCheck(p); } }.runTaskLater(pl, 5); + Player p = e.getPlayer(); + + pl.getTempflyManager().getAndSetTempfly(p); + + new BukkitRunnable() { + public void run() { + pl.flightManager.check(p); + if (p.isFlying()) { + pl.trailManager.trailCheck(p); + } + } + }.runTaskLater(pl, 5); + p.setFlySpeed(pl.configManager.flightSpeed); } // Because commands might affect permissions/fly diff --git a/FlightControl/src/main/java/org/spazzinq/flightcontrol/TempFlyManager.java b/FlightControl/src/main/java/org/spazzinq/flightcontrol/TempFlyManager.java new file mode 100644 index 00000000..685ef9a4 --- /dev/null +++ b/FlightControl/src/main/java/org/spazzinq/flightcontrol/TempFlyManager.java @@ -0,0 +1,127 @@ +/* + * This file is part of FlightControl-parent, which is licensed under the MIT License + * + * Copyright (c) 2019 Spazzinq + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.spazzinq.flightcontrol; + +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +public class TempFlyManager { + private FlightControl pl; + + private File tempflyFile; + private FileConfiguration tempflyData; + + @Getter private Set scheduledExpirations = new HashSet<>(); + + TempFlyManager(FlightControl pl) { + this.pl = pl; + + tempflyFile = new File(pl.getStorageFolder(), "tempfly.yml"); + reloadTempflyData(); + } + + void reloadTempflyData() { + if (!tempflyFile.exists()) { + try { //noinspection ResultOfMethodCallIgnored + tempflyFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + tempflyData = YamlConfiguration.loadConfiguration(tempflyFile); + + boolean modified = false; + + for (String strUUID : tempflyData.getKeys(false)) { + long expiration = tempflyData.getLong(strUUID); + + if (expiration > System.currentTimeMillis()) { + UUID uuid = UUID.fromString(strUUID); + + if (!scheduledExpirations.contains(uuid)) { + Player p = Bukkit.getPlayer(uuid); + + if (p != null && p.isOnline()) { + scheduleExpiration(p, expiration); + } + } + } else { + tempflyData.set(strUUID, null); + } + } + if (modified) saveTempfly(); + } + + public void setTempfly(Player p, long expiration) { + tempflyData.set(p.getUniqueId().toString(), expiration); + scheduleExpiration(p, expiration); + saveTempfly(); + } + + void getAndSetTempfly(Player p) { + if (tempflyData.contains(p.getUniqueId().toString()) && !scheduledExpirations.contains(p.getUniqueId())) { + scheduleExpiration(p, tempflyData.getLong(p.getUniqueId().toString())); + } + } + + public void removeTempfly(Player p) { + tempflyData.set(p.getUniqueId().toString(), null); + scheduledExpirations.remove(p.getUniqueId()); + pl.getFlightManager().getTempBypassList().remove(p); + pl.getFlightManager().check(p); + saveTempfly(); + } + + private void scheduleExpiration(Player p, long expiration) { + if (expiration > System.currentTimeMillis()) { + scheduledExpirations.add(p.getUniqueId()); + pl.getFlightManager().getTempBypassList().add(p); + + new BukkitRunnable() { + @Override public void run() { + removeTempfly(p); + } + }.runTaskLater(pl, (expiration - System.currentTimeMillis()) / 50); + } + } + + private void saveTempfly() { + try { + tempflyData.save(tempflyFile); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/FlightControl/src/main/java/org/spazzinq/flightcontrol/TrailManager.java b/FlightControl/src/main/java/org/spazzinq/flightcontrol/TrailManager.java index 1c19ec0e..9fde75eb 100644 --- a/FlightControl/src/main/java/org/spazzinq/flightcontrol/TrailManager.java +++ b/FlightControl/src/main/java/org/spazzinq/flightcontrol/TrailManager.java @@ -24,24 +24,38 @@ package org.spazzinq.flightcontrol; +import com.google.common.io.Files; +import lombok.Getter; import org.bukkit.GameMode; import org.bukkit.Location; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.potion.PotionEffectType; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; -import java.util.HashMap; -import java.util.Iterator; +import java.io.File; +import java.io.IOException; +import java.util.*; public final class TrailManager { private FlightControl pl; + + private File trailFile; + private FileConfiguration trailData; + @Getter private HashSet trailPrefs; + HashMap partTasks = new HashMap<>(); - TrailManager(FlightControl pl) { this.pl = pl; } + TrailManager(FlightControl pl) { + this.pl = pl; + trailFile = new File(pl.getStorageFolder(), "disabled_trail.yml"); + reloadTrailPrefs(); + } public void trailCheck(Player p) { - if (pl.particles != null && pl.configManager.trail && !pl.configManager.trailPrefs.contains(p.getUniqueId())) { + if (pl.particles != null && pl.configManager.trail && !trailPrefs.contains(p.getUniqueId())) { partTasks.put(p, new BukkitRunnable() { @Override public void run() { if (!(p.getGameMode() == GameMode.SPECTATOR || pl.vanish.vanished(p) || p.hasPotionEffect(PotionEffectType.INVISIBILITY))) { @@ -54,7 +68,7 @@ public void trailCheck(Player p) { } } - void trailRemove(Player p) { + public void trailRemove(Player p) { BukkitTask task = partTasks.remove(p); if (task != null) task.cancel(); } @@ -64,4 +78,53 @@ public void disableEnabledTrails() { //noinspection WhileLoopReplaceableByForEach while (it.hasNext()) trailRemove(it.next()); } + + // Per-player trail preferences + void reloadTrailPrefs() { + trailPrefs = new HashSet<>(); + if (!trailFile.exists()) { + File oldTrailFile = new File(pl.getDataFolder(), "disabled_trail.yml"); + + if (oldTrailFile.exists()) { + // Transfer old data + try { //noinspection UnstableApiUsage + Files.copy(oldTrailFile, trailFile); + } catch (IOException e) { + e.printStackTrace(); + } + //noinspection ResultOfMethodCallIgnored + oldTrailFile.delete(); + } else { + try { //noinspection ResultOfMethodCallIgnored + trailFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + } + trailData = YamlConfiguration.loadConfiguration(trailFile); + + if (trailData.isList("disabled_trail")) { + if (!trailData.getStringList("disabled_trail").isEmpty()) { + for (String uuid : trailData.getStringList("disabled_trail")) { + try { + if (uuid.matches("[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}")) + trailPrefs.add(UUID.fromString(uuid)); + } catch (IllegalArgumentException ignored) {} + } + } + } else trailData.createSection("disabled_trail"); + } + + void saveTrailPrefs() { // Saves personal trail preferences + if (trailData != null && trailFile != null) { + List prefs = new ArrayList<>(); + for (UUID uuid : trailPrefs) { + prefs.add(uuid.toString()); + } + trailData.set("disabled_trail", prefs); + try { trailData.save(trailFile); } catch (IOException e) { e.printStackTrace(); } + } + } } diff --git a/FlightControl/src/main/java/org/spazzinq/flightcontrol/Updater.java b/FlightControl/src/main/java/org/spazzinq/flightcontrol/Updater.java index ec037fed..786f46e4 100644 --- a/FlightControl/src/main/java/org/spazzinq/flightcontrol/Updater.java +++ b/FlightControl/src/main/java/org/spazzinq/flightcontrol/Updater.java @@ -49,7 +49,7 @@ boolean exists() { } catch (Exception ignored) { return false; } - return version.matches("\\d+(.\\d+)?") && newVersion.matches("\\d+(.\\d+)?") ? Double.parseDouble(newVersion) > Double.parseDouble(version) : !version.equals(newVersion); + return version.matches("\\d+(\\.\\d+)?") && newVersion.matches("\\d+(\\.\\d+)?") ? Double.parseDouble(newVersion) > Double.parseDouble(version) : !version.equals(newVersion); } private void dl() { @@ -58,7 +58,8 @@ private void dl() { URL website = new URL("https://github.com/Spazzinq/FlightControl/releases/download/" + newVersion + "/flightcontrol.jar"); ReadableByteChannel rbc = Channels.newChannel(website.openStream()); FileOutputStream fos = new FileOutputStream(new File( "plugins/flightcontrol.jar")); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); fos.close(); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); downloaded = true; } catch (Exception ignored) {} } diff --git a/FlightControl/src/main/java/org/spazzinq/flightcontrol/commands/FlightControlCommand.java b/FlightControl/src/main/java/org/spazzinq/flightcontrol/commands/FlightControlCommand.java index 7714bb1f..7333657d 100644 --- a/FlightControl/src/main/java/org/spazzinq/flightcontrol/commands/FlightControlCommand.java +++ b/FlightControl/src/main/java/org/spazzinq/flightcontrol/commands/FlightControlCommand.java @@ -36,7 +36,7 @@ public final class FlightControlCommand implements CommandExecutor, TabCompleter { private Map commands = new TreeMap() {{ - put("actionbar", "Send notifications through action bar"); + put("actionbar", "Send notifications through the actionbar"); put("autoenable", "Toggle automatic flight enabling"); put("autoupdate", "Toggle automatic updates"); put("combat", "Toggle combat disabling"); @@ -68,6 +68,7 @@ public FlightControlCommand(FlightControl pl) { buildDefaultHelp.append("&a").append(c.getKey()).append(" &7» &f").append(c.getValue()).append("\n"); } buildDefaultHelp.append(" \n&a/tt &7» &fPersonal trail toggle"); + buildDefaultHelp.append("\n&a/tempfly (player) [length] &7» &fActivate temporary flight"); defaultHelp = " \n" + buildDefaultHelp.toString(); } @@ -98,8 +99,7 @@ private String loadHelp(String[] args) { switch (autoComplete.isEmpty() ? args[0] : (autoComplete.size() == 1 ? autoComplete.get(0) : "")) { case "reload": - config.reloadConfig(); - pl.checkCurrentPlayers(); + pl.reload(); msg(s, "&a&lFlightControl &7» &aConfiguration successfully reloaded!"); break; case "update": @@ -150,7 +150,7 @@ private String loadHelp(String[] args) { break; case "speed": case "flightspeed": if (args.length == 2) { - if (args[1].matches("(\\d+)?(.\\d+)?")) { + if (args[1].matches("\\.\\d+|\\d+(\\.\\d+)?")) { float speed = Float.parseFloat(args[1]); float actualSpeed = pl.calcActualSpeed(speed); if (speed > -1 && speed < 11) { @@ -163,14 +163,14 @@ private String loadHelp(String[] args) { } msg(s, "&e&lFlightControl &7» &eSet the global flight speed to &f" + speed + "&e!"); } else msg(s, "&e&lFlightControl &7» &eGreat news! The global flight speed is already &f" + speed + "&e!"); - } else msg(s, "&e&lFlightControl &7» &ePlease provide a number between &f0 and 10 &e(inclusive)! The default speed is 1!"); + } else msg(s, "&e&lFlightControl &7» &ePlease provide a number between &f0 and 10 &e(inclusive)! The default speed is &f1&e!"); } else msg(s, "&e&lFlightControl &7» &ePlease provide a &fvalid decimal&e! Example: /fc speed 1"); } else if (args.length == 1) msg(s, "&e&lFlightControl &7» &ePlease provide a speed! Example: /fc speed 1"); else msg(s, "&e&lFlightControl &7» &eIncorrect usage! Usage: /fc speed (0-10)"); break; case "enemyrange": if (args.length == 2) { - if (args[1].matches("(\\d+)")) { + if (args[1].matches("\\d+|-1")) { int range = Integer.parseInt(args[1]); if (range > -2) { if (config.getFacEnemyRange() != range) { diff --git a/FlightControl/src/main/java/org/spazzinq/flightcontrol/commands/FlyCommand.java b/FlightControl/src/main/java/org/spazzinq/flightcontrol/commands/FlyCommand.java index d87ab406..73fbe657 100644 --- a/FlightControl/src/main/java/org/spazzinq/flightcontrol/commands/FlyCommand.java +++ b/FlightControl/src/main/java/org/spazzinq/flightcontrol/commands/FlyCommand.java @@ -24,6 +24,7 @@ package org.spazzinq.flightcontrol.commands; +import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -31,12 +32,14 @@ import org.spazzinq.flightcontrol.FlightControl; import org.spazzinq.flightcontrol.FlightManager; +import static org.spazzinq.flightcontrol.FlightControl.msg; + public final class FlyCommand implements CommandExecutor { private FlightControl pl; - private FlightManager manager; + private FlightManager flightManager; public FlyCommand(FlightControl pl) { this.pl = pl; - manager = pl.getFlightManager(); + flightManager = pl.getFlightManager(); } @Override public boolean onCommand(CommandSender s, Command cmd, String label, String[] args) { @@ -44,18 +47,28 @@ public FlyCommand(FlightControl pl) { if (s instanceof Player) { if (s.hasPermission("flightcontrol.fly") || s.hasPermission("essentials.fly")) { Player p = (Player) s; + if (p.getAllowFlight()) { - manager.disableFlight(p, true); - manager.getDisabledByPlayerList().add(p); - manager.getAlreadyCanMsgList().add(p); + flightManager.disableFlight(p, true); } else { - manager.check(p, p.getLocation(), true); - manager.getDisabledByPlayerList().remove(p); + flightManager.check(p, p.getLocation(), true); } } else FlightControl.msg(s, pl.getConfigManager().getNoPermission()); } else pl.getLogger().info("Only players can use this command (the console can't fly, can it?)"); - } else if (args.length == 1) pl.getTempFlyCommand().onCommand(s, cmd, label, args); + } else if (args.length == 1) { + Player p = Bukkit.getPlayer(args[0]); + // Allow admins to disable flight + if (p != null) { + FlightControl.msg(s, "&e&lFlightControl &7» &e" + (p.getAllowFlight() ? "Disabled" : "Attempted to enable") + " &f" + p.getName() + "&e's flight!"); + if (p.getAllowFlight()) { + flightManager.disableFlight(p, true); + } + else { + flightManager.check(p, p.getLocation(), true); + } + } else msg(s, "&e&lFlightControl &7» &ePlease provide a valid player!"); + } return true; } } diff --git a/FlightControl/src/main/java/org/spazzinq/flightcontrol/commands/TempFlyCommand.java b/FlightControl/src/main/java/org/spazzinq/flightcontrol/commands/TempFlyCommand.java index 24f78c5c..753ba4b5 100644 --- a/FlightControl/src/main/java/org/spazzinq/flightcontrol/commands/TempFlyCommand.java +++ b/FlightControl/src/main/java/org/spazzinq/flightcontrol/commands/TempFlyCommand.java @@ -31,45 +31,90 @@ import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; import org.spazzinq.flightcontrol.FlightControl; +import org.spazzinq.flightcontrol.FlightManager; +import org.spazzinq.flightcontrol.TempFlyManager; + +import static org.spazzinq.flightcontrol.FlightControl.msg; public final class TempFlyCommand implements CommandExecutor { private FlightControl pl; - public TempFlyCommand(FlightControl pl) { this.pl = pl; } + private FlightManager flightManager; + private TempFlyManager tempflyManager; + + public TempFlyCommand(FlightControl pl) { + this.pl = pl; + flightManager = pl.getFlightManager(); + tempflyManager = pl.getTempflyManager(); + } @Override public boolean onCommand(CommandSender s, Command cmd, String label, String[] args) { if (s instanceof ConsoleCommandSender || s.hasPermission("flightcontrol.flyother")) { if (args.length >= 1) { Player p = Bukkit.getPlayer(args[0]); if (p != null) { - // TODO Messages for self-tempfly (enabling it on yourself) - if (pl.getFlightManager().getTempBypassList().contains(p)) { - pl.getFlightManager().getTempBypassList().remove(p); - FlightControl.msg(s, "&e&lFlightControl &7» &eYou disabled " + p.getName() + "'s temporary bypass flight!"); + boolean isSelf = p == s; + if (flightManager.getTempBypassList().contains(p)) { + if (tempflyManager.getScheduledExpirations().contains(p.getUniqueId())) { + tempflyManager.removeTempfly(p); + } else { + flightManager.getTempBypassList().remove(p); + } + msg(s, "&e&lFlightControl &7» &eYou disabled &f" + (isSelf ? "your own" : p.getName() + "&e's") + " &etemporary bypass flight!"); } else { - // TODO timed temp-fly - // if (args.length == 2) { - // args[1] = args[1].toLowerCase(); - // if (args[1].matches("\\d+[smhd]")) { - // char unit = args[1].charAt(args[1].length() - 1); - // // Just in case it's a really - // long time = Long.parseLong(args[1].substring(0, args[1].length() - 1)) * 1000; - // - // switch (unit) { - // case 'm': time *= 60; break; - // case 'h': time *= 3600; break; - // case 'd': time *= 86400; break; - // default: break; - // } - // - // System.currentTimeMillis() + time - // } - // } - pl.getFlightManager().getTempBypassList().add(p); - FlightControl.msg(s, "&e&lFlightControl &7» &e" + p.getName() + " now has temporary bypass flight until the next server restart!"); + boolean set = false; + StringBuilder length = null; + if (args.length == 2) { + if (args[1].matches("\\d+([smhd]|seconds?|minutes?|hours?|days?)")) { + char unit = findUnit(args[1]); + // Just in case it's a really + long time = Long.parseLong(args[1].substring(0, args[1].length() - 1)); + boolean isNotOne = time != 1; + length = new StringBuilder(time + " "); + time *= 1000; + + switch (unit) { + case 'm': + length.append("minute"); + time *= 60; + break; + case 'h': + length.append("hour"); + time *= 3600; + break; + case 'd': + length.append("day"); + time *= 86400; + break; + default: + length.append("second"); + break; + } + if (isNotOne) length.append("s"); + + time += System.currentTimeMillis(); + + // Should always be above the current time, so no need to check + tempflyManager.setTempfly(p, time); + set = true; + } else msg(s, "&e&lFlightControl &7» &eInvalid format! Please use &f/tempfly (player) (length)&e! Follow the length with " + + "a unit of time (NO SPACE!): &fs (seconds), m (minutes), h (hours), d (days)&e."); + } else { + flightManager.getTempBypassList().add(p); + set = true; + } + if (set) msg(s, "&e&lFlightControl &7» &e" + (isSelf ? "You" : p.getName()) + " now " + (isSelf ? "have" : "has") + " temporary bypass flight " + + (length == null ? "until the next server restart/restart of FlightControl" : "for " + length)); } - } else FlightControl.msg(s, "&e&lFlightControl &7» &eInvalid player! Please provide a valid player to give temporary bypass flight!"); - } else FlightControl.msg(s, "&c&lFlightControl &7» &cPlease provide a player to give temporary bypass flight!"); - } else FlightControl.msg(s, pl.getConfigManager().getNoPermission()); + } else msg(s, "&e&lFlightControl &7» &ePlease provide a valid player!"); + } else msg(s, "&c&lFlightControl &7» &cPlease provide a player to give temporary bypass flight!"); + } else msg(s, pl.getConfigManager().getNoPermission()); return true; } + + private Character findUnit(String input) { + for (int i = 0; i < input.length(); i++) { + if (input.substring(i, i+1).matches("[smhd]")) return input.charAt(i); + } + return 's'; + } } diff --git a/FlightControl/src/main/java/org/spazzinq/flightcontrol/commands/ToggleTrailCommand.java b/FlightControl/src/main/java/org/spazzinq/flightcontrol/commands/ToggleTrailCommand.java new file mode 100644 index 00000000..cf6ee9bf --- /dev/null +++ b/FlightControl/src/main/java/org/spazzinq/flightcontrol/commands/ToggleTrailCommand.java @@ -0,0 +1,62 @@ +/* + * This file is part of FlightControl-parent, which is licensed under the MIT License + * + * Copyright (c) 2019 Spazzinq + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.spazzinq.flightcontrol.commands; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.spazzinq.flightcontrol.FlightControl; +import org.spazzinq.flightcontrol.TrailManager; + +import java.util.UUID; + +public class ToggleTrailCommand implements CommandExecutor { + private FlightControl pl; + private TrailManager manager; + + public ToggleTrailCommand(FlightControl pl) { + this.pl = pl; + manager = pl.getTrailManager(); + } + + @Override public boolean onCommand(CommandSender s, Command cmd, String label, String[] args) { + if (s instanceof Player) { + Player p = (Player) s; + UUID uuid = p.getUniqueId(); + if (manager.getTrailPrefs().contains(uuid)) { + manager.getTrailPrefs().remove(uuid); + // No need to check for trail enable because of command listener + FlightControl.msg(s, pl.getConfigManager().getEnableTrail(), pl.getConfigManager().isByActionBar()); + } + else { + manager.getTrailPrefs().add(uuid); + manager.trailRemove(p); + FlightControl.msg(s, pl.getConfigManager().getDisableTrail(), pl.getConfigManager().isByActionBar()); + } + } else pl.getLogger().info("Only players can use this command (the console isn't a player!)"); + return true; + } +} diff --git a/FlightControl/src/main/java/org/spazzinq/flightcontrol/utils/Actionbar.java b/FlightControl/src/main/java/org/spazzinq/flightcontrol/utils/Actionbar.java new file mode 100644 index 00000000..170c379f --- /dev/null +++ b/FlightControl/src/main/java/org/spazzinq/flightcontrol/utils/Actionbar.java @@ -0,0 +1,82 @@ +/* + * This file is part of FlightControl-parent, which is licensed under the MIT License + * + * Copyright (c) 2019 Spazzinq + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * Original code by ConnorLinfoot from + * https://github.com/ConnorLinfoot/ActionBarAPI/blob/master/src/main/java/com/connorlinfoot/actionbarapi/ActionBarAPI.java +*/ + +package org.spazzinq.flightcontrol.utils; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +public final class Actionbar { + private static String nms; + private static boolean oldMethod; + + static { + nms = Bukkit.getServer().getClass().getPackage().getName(); + nms = nms.substring(nms.lastIndexOf(".") + 1); + // 1_7 may work with protocol hack + if (nms.equalsIgnoreCase("v1_8_R1") || nms.startsWith("v1_7_")) oldMethod = true; + } + + public static void send(Player p, String msg) { + if (p.isOnline()) { + try { + Object packet; + Class packetPlayOutChatClass = Class.forName("net.minecraft.server." + nms + ".PacketPlayOutChat"); + if (oldMethod) { + Class chatSerializerClass = Class.forName("net.minecraft.server." + nms + ".ChatSerializer"); + Class iChatBaseComponentClass = Class.forName("net.minecraft.server." + nms + ".IChatBaseComponent"); + packet = packetPlayOutChatClass.getConstructor(new Class[]{iChatBaseComponentClass, byte.class}).newInstance( + iChatBaseComponentClass.cast(chatSerializerClass.getDeclaredMethod("a", String.class).invoke( + chatSerializerClass, "{\"text\": \"" + msg + "\"}")), (byte) 2); + } else { + Object chatComponentText = Class.forName("net.minecraft.server." + nms + ".ChatComponentText").getConstructor(new Class[]{String.class}).newInstance(msg); + Class iChatBaseComponentClass = Class.forName("net.minecraft.server." + nms + ".IChatBaseComponent"); + try { + Class chatMessageTypeClass = Class.forName("net.minecraft.server." + nms + ".ChatMessageType"); + Object chatMessageType = null; + for (Object obj : chatMessageTypeClass.getEnumConstants()) if (obj.toString().equals("GAME_INFO")) chatMessageType = obj; + packet = packetPlayOutChatClass.getConstructor(new Class[]{iChatBaseComponentClass, chatMessageTypeClass}).newInstance(chatComponentText, chatMessageType); + } catch (ClassNotFoundException e) { packet = packetPlayOutChatClass.getConstructor(new Class[]{iChatBaseComponentClass, byte.class}).newInstance(chatComponentText, (byte) 2); } + } + Class craftPlayerClass = Class.forName("org.bukkit.craftbukkit." + nms + ".entity.CraftPlayer"); + Object craftPlayerHandle = craftPlayerClass.getDeclaredMethod("getHandle").invoke(craftPlayerClass.cast(p)); + Object playerConnection = craftPlayerHandle.getClass().getDeclaredField("playerConnection").get(craftPlayerHandle); + playerConnection.getClass().getDeclaredMethod("sendPacket", Class.forName("net.minecraft.server." + nms + ".Packet")).invoke(playerConnection, packet); + } catch (Exception e) { e.printStackTrace(); } + } + } +// static void send(Player p, String msg, double duration) { +// sending.add(p); +// send(p, msg); +// // Sends empty msg at the end of the duration. Allows messages shorter than 3 seconds, ensures precision. +// if (duration >= 0) new BukkitRunnable() { public void run() { if (!sending.contains(p)) send(p, ""); sending.remove(p); } }.runTaskLater(pl, (long) duration + 1); +// // Re-sends the messages every 3 seconds so it doesn't go away from the p's screen. +// while (duration > 40) { duration -= 40; new BukkitRunnable() { public void run() { if (!sending.contains(p)) send(p, msg); } }.runTaskLater(pl, (long) duration); } +// } +} diff --git a/FlightControl/src/main/resources/config.yml b/FlightControl/src/main/resources/config.yml index 7c083754..650c2816 100644 --- a/FlightControl/src/main/resources/config.yml +++ b/FlightControl/src/main/resources/config.yml @@ -37,7 +37,7 @@ settings: # Controls flight speed (default speed is 1) # The speed values match Essential's /flyspeed command (the number range is 0-10) flight_speed: 1.0 - # Requires CombatTagPlus, CombatLogX, or AntiCombatLogging + # Requires CombatTagPlus, CombatLogX, CombatLogPro, or AntiCombatLogging # NOTE: in the combat plugin config, deactivate its option to disable flight while in combat to prevents issues disable_flight_in_combat: false # Prevents fall damage when flight is disabled mid-air by FlightControl diff --git a/FlightControl/src/main/resources/plugin.yml b/FlightControl/src/main/resources/plugin.yml index 70402255..8eb0e3b9 100644 --- a/FlightControl/src/main/resources/plugin.yml +++ b/FlightControl/src/main/resources/plugin.yml @@ -6,6 +6,7 @@ author: Spazzinq description: "An elegant solution for controlling player flight" softdepend: [AntiCombatLogging, CombatLogX, CombatTagPlus, Essentials, Factions, PlotSquared, WorldGuard, Plugman] +# FIXME Add back permissions to commands commands: flightcontrol: description: FlightControl administration diff --git a/pom.xml b/pom.xml index 509bbd73..f6f1a5e6 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ pom ${revision} - 3.3 + 3.4 FlightControl