package com.sk89q.commandbook; import com.sk89q.commandbook.session.PersistentSession; import com.sk89q.commandbook.session.SessionComponent; import com.sk89q.commandbook.util.InputUtil; import com.sk89q.commandbook.util.entity.player.PlayerUtil; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.minecraft.util.commands.NestedCommand; import com.zachsthings.libcomponents.ComponentInformation; import com.zachsthings.libcomponents.InjectComponent; import com.zachsthings.libcomponents.bukkit.BukkitComponent; import com.zachsthings.libcomponents.config.ConfigurationBase; import com.zachsthings.libcomponents.config.Setting; import org.bukkit.ChatColor; import org.bukkit.GameMode; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerChangedWorldEvent; import org.bukkit.event.player.PlayerGameModeChangeEvent; import org.bukkit.event.player.PlayerJoinEvent; @ComponentInformation(friendlyName = "Flight", desc = "Allows players to fly and control flight speed") public class FlightComponent extends BukkitComponent implements Listener { private static final float DEFAULT_FLIGHT_SPEED = 0.1f, DEFAULT_WALK_SPEED = 0.2f; @InjectComponent private SessionComponent sessions; private LocalConfiguration config; @Override public void enable() { CommandBook.registerEvents(this); registerCommands(Commands.class); config = configure(new LocalConfiguration()); } private static class LocalConfiguration extends ConfigurationBase { @Setting("auto-enable") public boolean autoEnable = false; @Setting("check-world-change") public boolean checkWorldChange = true; } public static class FlightSession extends PersistentSession { private FlightSession() { super(-1); } @Setting("can-fly") private boolean canFly; } public class Commands { @Command(aliases = "fly", usage = "[player]", desc = "Toggle flight for a player", flags = "s", min = 0, max = 1) public void fly(CommandContext args, CommandSender sender) throws CommandException { Iterable<Player> targets = null; boolean included = false; targets = InputUtil.PlayerParser.detectTargets(sender, args, "commandbook.flight.toggle"); for (Player player : targets) { FlightSession session = sessions.getSession(FlightSession.class, player); session.canFly = session.canFly && !player.getAllowFlight() || !session.canFly; player.setAllowFlight(session.canFly); if (!included && player.equals(sender)) { included = true; } if (!args.hasFlag('s')) { player.sendMessage(ChatColor.YELLOW + "You can " + (session.canFly ? "now" : "no longer") + " fly!"); } } if (!included && !args.hasFlag('s')) { sender.sendMessage(ChatColor.YELLOW + "Flight mode toggled for player(s)."); } } @Command(aliases = "speed", desc = "Set the speed of player movement") @NestedCommand(SpeedCommands.class) public void speed() { } @Command(aliases = "reverse", desc = "Go in reverse!", usage = "[player]", flags = "s", min = 0, max = 1) public void reverse(CommandContext args, CommandSender sender) throws CommandException { Iterable<Player> targets = null; boolean included = false; targets = InputUtil.PlayerParser.detectTargets(sender, args, "commandbook.flight.reverse"); for (Player player : targets) { player.setFlySpeed(-player.getFlySpeed()); // player.setWalkSpeed(-player.getWalkSpeed()); // Gives weird video artifacts TODO: Bug DB about disabling viewport distortions when we change walk speed if (!sender.equals(player)) { sender.sendMessage(ChatColor.YELLOW + player.getName() + " has been put in reverse!"); } if (!included && player.equals(sender)) { included = true; } if (!args.hasFlag('s')) { player.sendMessage(ChatColor.YELLOW + "And now in reverse!"); } } if (!included && !args.hasFlag('s')) { sender.sendMessage(ChatColor.YELLOW + "Speed reversed for player(s)."); } } } public class SpeedCommands { @Command(aliases = {"flight", "fly", "f"}, usage = "[player] [speed-multiplier]", desc = "Set the flying speed multiplier") public void flightSpeed(CommandContext args, CommandSender sender) throws CommandException { Player player; float flightMultiplier = 1f; if (args.argsLength() == 2) { player = InputUtil.PlayerParser.matchSinglePlayer(sender, args.getString(0)); flightMultiplier = (float) args.getDouble(1); } else if (args.argsLength() == 1) { try { flightMultiplier = (float) args.getDouble(0); player = PlayerUtil.checkPlayer(sender); } catch (NumberFormatException e) { player = InputUtil.PlayerParser.matchSinglePlayer(sender, args.getString(0)); } } else { player = PlayerUtil.checkPlayer(sender); } CommandBook.inst().checkPermission(sender, "commandbook.speed.flight" + (player.equals(sender) ? "" : ".other")); final float flightSpeed = DEFAULT_FLIGHT_SPEED * flightMultiplier; // Apply multiplier try { player.setFlySpeed(flightSpeed); } catch (IllegalArgumentException e) { // We gave an invalid value, tell the user nicely if (flightSpeed < DEFAULT_WALK_SPEED) { throw new CommandException("Speed multiplier too low: " + flightMultiplier); } else if (flightSpeed > DEFAULT_WALK_SPEED) { throw new CommandException("Speed multiplier too high: " + flightMultiplier); } } player.sendMessage(ChatColor.YELLOW + "Your flight speed has been set to " + flightMultiplier + "x"); if (sender != player) { sender.sendMessage(ChatColor.YELLOW + player.getName() + "'s flight speed has been set to " + flightMultiplier + "x"); } } @Command(aliases = {"walk", "walking", "w"}, usage = "[player] [speed-multiplier]", desc = "Set the walking speed multiplier") public void walkSpeed(CommandContext args, CommandSender sender) throws CommandException { Player player; float walkMultiplier = 1f; if (args.argsLength() == 2) { player = InputUtil.PlayerParser.matchSinglePlayer(sender, args.getString(0)); walkMultiplier = (float) args.getDouble(1); } else if (args.argsLength() == 1) { try { walkMultiplier = (float) args.getDouble(0); player = PlayerUtil.checkPlayer(sender); } catch (NumberFormatException e) { player = InputUtil.PlayerParser.matchSinglePlayer(sender, args.getString(0)); } } else { player = PlayerUtil.checkPlayer(sender); } CommandBook.inst().checkPermission(sender, "commandbook.speed.walk" + (player.equals(sender) ? "" : ".other")); final float walkSpeed = DEFAULT_WALK_SPEED * walkMultiplier; // Apply multiplier try { player.setWalkSpeed(walkSpeed); } catch (IllegalArgumentException e) { // We gave an invalid value, tell the user nicely if (walkSpeed < DEFAULT_WALK_SPEED) { throw new CommandException("Speed multiplier too low: " + walkMultiplier); } else if (walkSpeed > DEFAULT_WALK_SPEED) { throw new CommandException("Speed multiplier too high: " + walkMultiplier); } } player.sendMessage(ChatColor.YELLOW + "Your walking speed has been set to " + walkMultiplier + "x"); if (sender != player) { sender.sendMessage(ChatColor.YELLOW + player.getName() + "'s walking speed has been set to " + walkMultiplier + "x"); } } } @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { if (config.autoEnable) { final Player player = event.getPlayer(); CommandBook.server().getScheduler().runTaskLater(CommandBook.inst(), new Runnable() { @Override public void run() { if (CommandBook.inst().hasPermission(player, "commandbook.flight.onjoin")) { FlightSession session = sessions.getSession(FlightSession.class, player); player.setAllowFlight(session.canFly = true); //noinspection deprecation if (!player.isOnGround()) { player.setFlying(true); } } } }, 1); } } @EventHandler public void onPlayerChangeGameMode(PlayerGameModeChangeEvent event) { Player player = event.getPlayer(); FlightSession session = sessions.getSession(FlightSession.class, player); if (event.getNewGameMode() != GameMode.CREATIVE) { player.setAllowFlight(session.canFly); } } @EventHandler public void onPlayerworldChange(PlayerChangedWorldEvent event) { Player player = event.getPlayer(); FlightSession session = sessions.getSession(FlightSession.class, player); if (config.checkWorldChange && player.getGameMode() != GameMode.CREATIVE && !CommandBook.inst().hasPermission(player, "commandbook.flight." + player.getWorld().getName())) { player.setAllowFlight(session.canFly = false); } } }