From c85d522dd997986a70e6cd577b5ee230663e24b3 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Sun, 1 Nov 2020 17:14:22 +0100 Subject: [PATCH] Implement ReplayCommand and partial lobby features (double jump) --- src/de/steamwar/spectatesystem/Config.java | 37 ++++++- .../steamwar/spectatesystem/PlayerSetup.java | 103 ++++++++++++++++++ .../spectatesystem/SpectateSystem.java | 15 +-- .../commands/ReplayCommand.java | 49 +++++++++ .../listener/CancelListener.java | 76 +++++++++++++ .../spectatesystem/listener/JoinListener.java | 43 +------- ...ArenaListener.java => PlayerListener.java} | 99 +++++++++++------ 7 files changed, 333 insertions(+), 89 deletions(-) create mode 100644 src/de/steamwar/spectatesystem/PlayerSetup.java create mode 100644 src/de/steamwar/spectatesystem/commands/ReplayCommand.java rename src/de/steamwar/spectatesystem/listener/{ArenaListener.java => PlayerListener.java} (64%) diff --git a/src/de/steamwar/spectatesystem/Config.java b/src/de/steamwar/spectatesystem/Config.java index dcb4f2f..fe53d46 100644 --- a/src/de/steamwar/spectatesystem/Config.java +++ b/src/de/steamwar/spectatesystem/Config.java @@ -53,7 +53,6 @@ public class Config { private static final int TeamBluetoReddistanceX; private static final int TeamBluetoReddistanceY; public static final int TeamBluetoReddistanceZ; - public static final Location SpecSpawn; public static final int underArenaBorder; public static final int BorderFromSchematic; public static final int upperArenaBorder; @@ -68,6 +67,7 @@ public class Config { public static final boolean TeamRedRotate; public static final boolean TeamBlueRotate; + //tech hider parameter public static final boolean TechhiderActive; public static final Set HiddenBlocks; @@ -81,6 +81,15 @@ public class Config { public static final int port = 2222; + // Lobby parameters + public static final Location SpecSpawn; + public static final int BorderMinX; + public static final int BorderMinY; + public static final int BorderMinZ; + public static final int BorderMaxX; + public static final int BorderMaxY; + public static final int BorderMaxZ; + static{ World world = Bukkit.getWorlds().get(0); File worldConfigFile = new File(world.getWorldFolder(), "config.yml"); @@ -91,11 +100,18 @@ public class Config { FileConfiguration worldconfig = YamlConfiguration.loadConfiguration(worldConfigFile); if(!new File(SpectateSystem.get().getDataFolder(), "config.yml").exists()) { - Bukkit.getLogger().log(Level.SEVERE, "Arenaconfig fehlt!"); + Bukkit.getLogger().log(Level.SEVERE, "FightSystem config fehlt!"); Bukkit.shutdown(); } FileConfiguration config = SpectateSystem.get().getConfig(); + File spectateconfigFile = new File(SpectateSystem.get().getDataFolder(), "spectate.yml"); + if(!spectateconfigFile.exists()) { + Bukkit.getLogger().log(Level.SEVERE, "Spectate config fehlt!"); + Bukkit.shutdown(); + } + FileConfiguration spectateconfig = YamlConfiguration.loadConfiguration(spectateconfigFile); + int schemsizeX = worldconfig.getInt("Arena.Schemsize.x"); int schemsizeY = worldconfig.getInt("Arena.Schemsize.y"); int schemsizeZ = worldconfig.getInt("Arena.Schemsize.z"); @@ -146,10 +162,23 @@ public class Config { TeamRedPasteX = TeamRedCornerX + SchemsizeX / 2; TeamRedPasteZ = TeamRedCornerZ + SchemsizeZ / 2; - SpecSpawn = new Location(world, + /*SpecSpawn = new Location(world, TeamBluePasteX + TeamBluetoReddistanceX/2.0, TeamBlueCornerY + TeamBluetoReddistanceY/2.0 + SchemsizeY/2.0, - TeamBluePasteZ + TeamBluetoReddistanceZ/2.0); + TeamBluePasteZ + TeamBluetoReddistanceZ/2.0);*/ + SpecSpawn = new Location(world, + spectateconfig.getDouble("Spawn.X"), + spectateconfig.getDouble("Spawn.Y"), + spectateconfig.getDouble("Spawn.Z"), + (float)spectateconfig.getDouble("Spawn.Yaw"), + (float)spectateconfig.getDouble("Spawn.Pitch")); + + BorderMinX = spectateconfig.getInt("Border.MinX"); + BorderMinY = spectateconfig.getInt("Border.MinY"); + BorderMinZ = spectateconfig.getInt("Border.MinZ"); + BorderMaxX = spectateconfig.getInt("Border.MaxX"); + BorderMaxY = spectateconfig.getInt("Border.MaxY"); + BorderMaxZ = spectateconfig.getInt("Border.MaxZ"); boolean teamRedRotate; boolean teamBlueRotate; diff --git a/src/de/steamwar/spectatesystem/PlayerSetup.java b/src/de/steamwar/spectatesystem/PlayerSetup.java new file mode 100644 index 0000000..3e1bd17 --- /dev/null +++ b/src/de/steamwar/spectatesystem/PlayerSetup.java @@ -0,0 +1,103 @@ +package de.steamwar.spectatesystem; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.wrappers.EnumWrappers; +import com.comphenix.protocol.wrappers.PlayerInfoData; +import com.comphenix.protocol.wrappers.WrappedChatComponent; +import com.comphenix.protocol.wrappers.WrappedGameProfile; +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; + +public class PlayerSetup { + private PlayerSetup(){} + + private static final boolean SPAWN_IN_ARENA; + private static final Set arenaPlayers = new HashSet<>(); + + static{ + SPAWN_IN_ARENA = locInArena(Config.SpecSpawn); + } + + public static void playerJoins(Player player){ + if(SPAWN_IN_ARENA) + playerJoinsArena(player); + else + playerJoinsLobby(player); + } + + public static boolean isMovingPlayerInArena(Player player, Location to){ + boolean inArena = locInArena(to); + boolean inArenaPlayers = arenaPlayers.contains(player); + + if(inArena && !inArenaPlayers) + playerJoinsArena(player); + else if(!inArena && inArenaPlayers) + playerJoinsLobby(player); + + return inArena; + } + + public static void playerLeaves(Player player){ + arenaPlayers.remove(player); + } + + private static boolean locInArena(Location loc){ + return Config.ArenaMinX <= loc.getX() && Config.ArenaMaxX >= loc.getX() && + Config.ArenaMinZ <= loc.getZ() && Config.ArenaMaxZ >= loc.getZ(); + } + + private static void playerJoinsLobby(Player player){ + player.setAllowFlight(true); + player.setFlying(false); + player.teleport(Config.SpecSpawn); + player.getInventory().clear(); + for(Player currentPlayer : Bukkit.getServer().getOnlinePlayers()) { + if(currentPlayer.getUniqueId() != player.getUniqueId() && currentPlayer.getGameMode() != GameMode.SPECTATOR) { + currentPlayer.showPlayer(SpectateSystem.get(), player); + player.showPlayer(SpectateSystem.get(), currentPlayer); + } + } + player.setGameMode(GameMode.ADVENTURE); + player.setHealth(20); + player.setFoodLevel(20); + arenaPlayers.remove(player); + } + + private static void playerJoinsArena(Player player){ + player.setAllowFlight(false); + player.setGameMode(GameMode.SPECTATOR); + for(Player currentPlayer : Bukkit.getServer().getOnlinePlayers()) { + if(currentPlayer.getUniqueId() != player.getUniqueId() && currentPlayer.getGameMode() == GameMode.SPECTATOR) { + currentPlayer.hidePlayer(SpectateSystem.get(), player); + player.hidePlayer(SpectateSystem.get(), currentPlayer); + } + } + Bukkit.getScheduler().runTaskLater(SpectateSystem.get(), () -> { + PacketContainer gm1packet = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.PLAYER_INFO); + gm1packet.getPlayerInfoAction().write(0, EnumWrappers.PlayerInfoAction.UPDATE_GAME_MODE); + List playerInfoActions = new ArrayList<>(); + playerInfoActions.add(new PlayerInfoData(WrappedGameProfile.fromPlayer(player), 1, EnumWrappers.NativeGameMode.CREATIVE, WrappedChatComponent.fromText(player.getDisplayName()))); + gm1packet.getPlayerInfoDataLists().write(0, playerInfoActions); + try { + ProtocolLibrary.getProtocolManager().sendServerPacket(player, gm1packet); + } catch (InvocationTargetException ex) { + Bukkit.getLogger().log(Level.SEVERE, "Invocation target exception", ex); + } + }, 2); + + player.getInventory().clear(); + player.teleport(Config.SpecSpawn); + arenaPlayers.add(player); + } +} diff --git a/src/de/steamwar/spectatesystem/SpectateSystem.java b/src/de/steamwar/spectatesystem/SpectateSystem.java index 870eab3..644b029 100644 --- a/src/de/steamwar/spectatesystem/SpectateSystem.java +++ b/src/de/steamwar/spectatesystem/SpectateSystem.java @@ -19,14 +19,14 @@ package de.steamwar.spectatesystem; +import de.steamwar.spectatesystem.commands.ReplayCommand; import de.steamwar.spectatesystem.elements.RScoreboard; -import de.steamwar.spectatesystem.listener.ArenaListener; +import de.steamwar.spectatesystem.listener.PlayerListener; import de.steamwar.spectatesystem.listener.CancelListener; import de.steamwar.spectatesystem.listener.JoinListener; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; -import java.io.File; import java.io.IOException; import java.util.logging.Level; @@ -41,7 +41,7 @@ public class SpectateSystem extends JavaPlugin { instance = this; scoreboard = new RScoreboard(); new JoinListener(); - new ArenaListener(); + new PlayerListener(); new CancelListener(); try { acceptor = new ConnectionAcceptor(); @@ -49,14 +49,7 @@ public class SpectateSystem extends JavaPlugin { Bukkit.getLogger().log(Level.SEVERE, "Could not open ConnectionAcceptor", e); } - String fightFile = System.getProperty("fightFile"); - if(fightFile != null){ - try { - new FightfileConnection(new File(fightFile)); - } catch (IOException e) { - Bukkit.getLogger().log(Level.WARNING, "Could not start reading file", e); - } - } + Bukkit.getPluginCommand("replay").setExecutor(new ReplayCommand()); } @Override diff --git a/src/de/steamwar/spectatesystem/commands/ReplayCommand.java b/src/de/steamwar/spectatesystem/commands/ReplayCommand.java new file mode 100644 index 0000000..fafc2fc --- /dev/null +++ b/src/de/steamwar/spectatesystem/commands/ReplayCommand.java @@ -0,0 +1,49 @@ +package de.steamwar.spectatesystem.commands; + +import de.steamwar.spectatesystem.FightfileConnection; +import de.steamwar.sql.SteamwarUser; +import de.steamwar.sql.UserGroup; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.io.File; +import java.io.IOException; +import java.util.EnumSet; +import java.util.Set; +import java.util.logging.Level; + +public class ReplayCommand implements CommandExecutor { + + private static final Set allowedGroups = EnumSet.of(UserGroup.Admin, UserGroup.Developer, UserGroup.Moderator); + + @Override + public boolean onCommand(CommandSender sender, Command command, String alias, String[] args) { + if(sender instanceof Player){ + Player player = (Player) sender; + SteamwarUser user = SteamwarUser.get(player.getUniqueId()); + if(!allowedGroups.contains(user.getUserGroup())){ + player.sendMessage("§eSteam§8War» §cUnbekannter Befehl."); + return false; + } + } + + if(args.length != 1){ + sender.sendMessage("§eSteam§8War» §c/replay [Dateipfad]"); + return false; + } + + try { + new FightfileConnection(new File(args[0])); + } catch (IOException e) { + Bukkit.getLogger().log(Level.WARNING, "Could not start reading file", e); + sender.sendMessage("§eSteam§8War» §cReplay konnte nicht gestartet werden."); + return false; + } + + sender.sendMessage("§eSteam§8War» §aReplay gestartet."); + return false; + } +} diff --git a/src/de/steamwar/spectatesystem/listener/CancelListener.java b/src/de/steamwar/spectatesystem/listener/CancelListener.java index 7b5fa74..07eac53 100644 --- a/src/de/steamwar/spectatesystem/listener/CancelListener.java +++ b/src/de/steamwar/spectatesystem/listener/CancelListener.java @@ -19,8 +19,23 @@ package de.steamwar.spectatesystem.listener; +import org.bukkit.craftbukkit.v1_15_R1.CraftChunk; +import org.bukkit.entity.EntityType; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockExplodeEvent; import org.bukkit.event.block.BlockPhysicsEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.FoodLevelChangeEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; +import org.bukkit.event.player.PlayerSwapHandItemsEvent; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.event.world.ChunkUnloadEvent; +import org.bukkit.event.world.WorldLoadEvent; public class CancelListener extends BasicListener { @@ -29,4 +44,65 @@ public class CancelListener extends BasicListener { event.setCancelled(true); } + @EventHandler + public void onChunkLoad(ChunkLoadEvent e){ + ((CraftChunk)e.getChunk()).getHandle().mustNotSave = true; + } + + @EventHandler + public void onChunkSave(ChunkUnloadEvent e){ + e.setSaveChunk(false); + } + + @EventHandler + public void onWorldLoad(WorldLoadEvent e){ + e.getWorld().setAutoSave(false); + } + + @EventHandler + public void onEntityExplosion(EntityExplodeEvent e){ + e.setCancelled(true); + } + + @EventHandler + public void onBlockExplosion(BlockExplodeEvent e){ + e.setCancelled(true); + } + + @EventHandler + public void handlePlayerDropItem(PlayerDropItemEvent event) { + event.setCancelled(true); + } + + @EventHandler + public void handlePlayerPickupItem(PlayerPickupItemEvent event) { + event.setCancelled(true); + } + + @EventHandler(priority = EventPriority.LOWEST) + public void handleInventoryClick(InventoryClickEvent event) { + event.setCancelled(true); + } + + @EventHandler + public void handlePlayerSwapHandItemsEvent(PlayerSwapHandItemsEvent event) { + event.setCancelled(true); + } + + + @EventHandler(priority = EventPriority.LOW) + public void handlePlayerInteract(PlayerInteractEvent event) { + event.setCancelled(true); + } + + @EventHandler + public void handleEntityDamage(EntityDamageEvent event) { + if(event.getEntityType() != EntityType.PLAYER) return; + event.setCancelled(true); + } + + @EventHandler + public void handleFoodLevelChange(FoodLevelChangeEvent event) { + event.setCancelled(true); + } } diff --git a/src/de/steamwar/spectatesystem/listener/JoinListener.java b/src/de/steamwar/spectatesystem/listener/JoinListener.java index 7506fb9..65a3631 100644 --- a/src/de/steamwar/spectatesystem/listener/JoinListener.java +++ b/src/de/steamwar/spectatesystem/listener/JoinListener.java @@ -19,63 +19,30 @@ package de.steamwar.spectatesystem.listener; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.wrappers.EnumWrappers; -import com.comphenix.protocol.wrappers.PlayerInfoData; -import com.comphenix.protocol.wrappers.WrappedChatComponent; -import com.comphenix.protocol.wrappers.WrappedGameProfile; import de.steamwar.scoreboard.SWScoreboard; -import de.steamwar.spectatesystem.Config; +import de.steamwar.spectatesystem.PlayerSetup; import de.steamwar.spectatesystem.SpectateSystem; import de.steamwar.spectatesystem.elements.REntity; -import org.bukkit.Bukkit; -import org.bukkit.GameMode; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; - public class JoinListener extends BasicListener { @EventHandler public void onJoin(PlayerJoinEvent e){ + e.setJoinMessage(null); Player player = e.getPlayer(); REntity.playerJoins(player); - - player.setGameMode(GameMode.SPECTATOR); - for(Player currentPlayer : Bukkit.getServer().getOnlinePlayers()) { - if(currentPlayer.getUniqueId() != player.getUniqueId() && currentPlayer.getGameMode() == GameMode.SPECTATOR) { - currentPlayer.hidePlayer(SpectateSystem.get(), player); - player.hidePlayer(SpectateSystem.get(), currentPlayer); - } - } - Bukkit.getScheduler().runTaskLater(SpectateSystem.get(), () -> { - PacketContainer gm1packet = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.PLAYER_INFO); - gm1packet.getPlayerInfoAction().write(0, EnumWrappers.PlayerInfoAction.UPDATE_GAME_MODE); - List playerInfoActions = new ArrayList<>(); - playerInfoActions.add(new PlayerInfoData(WrappedGameProfile.fromPlayer(player), 1, EnumWrappers.NativeGameMode.CREATIVE, WrappedChatComponent.fromText(player.getDisplayName()))); - gm1packet.getPlayerInfoDataLists().write(0, playerInfoActions); - try { - ProtocolLibrary.getProtocolManager().sendServerPacket(player, gm1packet); - } catch (InvocationTargetException ex) { - Bukkit.getLogger().log(Level.SEVERE, "Invocation target exception", ex); - } - }, 2); - - player.getInventory().clear(); - player.teleport(Config.SpecSpawn); + PlayerSetup.playerJoins(player); SWScoreboard.createScoreboard(player, SpectateSystem.getScoreboard()); } @EventHandler public void onLeave(PlayerQuitEvent e){ SWScoreboard.removeScoreboard(e.getPlayer()); + PlayerSetup.playerLeaves(e.getPlayer()); + e.setQuitMessage(null); } } diff --git a/src/de/steamwar/spectatesystem/listener/ArenaListener.java b/src/de/steamwar/spectatesystem/listener/PlayerListener.java similarity index 64% rename from src/de/steamwar/spectatesystem/listener/ArenaListener.java rename to src/de/steamwar/spectatesystem/listener/PlayerListener.java index 1fb4249..c63b5cd 100644 --- a/src/de/steamwar/spectatesystem/listener/ArenaListener.java +++ b/src/de/steamwar/spectatesystem/listener/PlayerListener.java @@ -20,41 +20,39 @@ package de.steamwar.spectatesystem.listener; import de.steamwar.spectatesystem.Config; +import de.steamwar.spectatesystem.PlayerSetup; import de.steamwar.spectatesystem.SpectateSystem; import de.steamwar.spectatesystem.util.Region; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.TextComponent; -import org.bukkit.BanList; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.craftbukkit.v1_15_R1.CraftChunk; +import org.bukkit.*; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; -import org.bukkit.event.block.BlockExplodeEvent; -import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerTeleportEvent; -import org.bukkit.event.world.ChunkLoadEvent; -import org.bukkit.event.world.ChunkUnloadEvent; -import org.bukkit.event.world.WorldLoadEvent; +import org.bukkit.event.player.PlayerToggleFlightEvent; +import org.bukkit.util.Vector; import java.util.logging.Level; -public class ArenaListener extends BasicListener { +public class PlayerListener extends BasicListener { - private static final String DENY_ARENA = "§cDu darfst die Arena nicht verlassen"; private static final String DENY_TEAM = "§cDu darfst nicht zu den Teams"; @EventHandler public void onMove(PlayerMoveEvent event) { Location to = event.getTo(); - assert to != null; - if(!Region.isIn2DRegion(to, Config.ArenaMinX, Config.ArenaMinZ, Config.ArenaMaxX, Config.ArenaMaxZ) || to.getY() <= Config.underArenaBorder) - reset(event, DENY_ARENA); + if(PlayerSetup.isMovingPlayerInArena(event.getPlayer(), to)) + checkMovementInArena(event, to); + else + checkMovementInLobby(event, to); + } + + private void checkMovementInArena(PlayerMoveEvent event, Location to){ boolean inArenaY = to.getY() + 1.8 <= Config.upperArenaBorder; boolean inBlueArea = inArenaY && Region.isIn2DRange(to, Config.TeamBlueCornerX, Config.TeamBlueCornerZ, Config.SchemsizeX, Config.SchemsizeZ, Config.BorderFromSchematic); boolean inRedArea = inArenaY && Region.isIn2DRange(to, Config.TeamRedCornerX, Config.TeamRedCornerZ, Config.SchemsizeX, Config.SchemsizeZ, Config.BorderFromSchematic); @@ -68,6 +66,28 @@ public class ArenaListener extends BasicListener { checkInInnerArea(event.getPlayer(), to, Config.TeamRedCornerX, Config.TeamRedCornerZ); } + private void checkMovementInLobby(PlayerMoveEvent event, Location to){ + if(!isInRegion( + new Vector(Config.BorderMinX, Config.BorderMinY, Config.BorderMinZ), + new Vector(Config.BorderMaxX, Config.BorderMaxY, Config.BorderMaxZ), + to.toVector())){ + event.getPlayer().teleport(event.getFrom()); + } + } + + private boolean isInRegion(Vector minPoint, Vector maxPoint, Vector location) { + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + return x >= minPoint.getBlockX() + && x <= maxPoint.getBlockX() + && y >= minPoint.getBlockY() + && y <= maxPoint.getBlockY() + && z >= minPoint.getBlockZ() + && z <= maxPoint.getBlockZ(); + } + private void checkInInnerArea(Player player, Location to, int teamCornerX, int teamCornerZ){ boolean inArenaY = to.getY() + 1.8 <= Config.TeamBlueCornerY + Config.SchemsizeY; boolean inArea = inArenaY && Region.isIn2DRange(to, teamCornerX, teamCornerZ, Config.SchemsizeX, Config.SchemsizeZ, 0); @@ -95,26 +115,6 @@ public class ArenaListener extends BasicListener { } } - @EventHandler - public void onChunkSave(ChunkUnloadEvent e){ - e.setSaveChunk(false); - } - - @EventHandler - public void onWorldLoad(WorldLoadEvent e){ - e.getWorld().setAutoSave(false); - } - - @EventHandler - public void onEntityExplosion(EntityExplodeEvent e){ - e.setCancelled(true); - } - - @EventHandler - public void onBlockExplosion(BlockExplodeEvent e){ - e.setCancelled(true); - } - @EventHandler public void onChat(AsyncPlayerChatEvent e){ e.setCancelled(true); @@ -123,7 +123,34 @@ public class ArenaListener extends BasicListener { } @EventHandler - public void onChunkLoad(ChunkLoadEvent e){ - ((CraftChunk)e.getChunk()).getHandle().mustNotSave = true; + public void handlePlayerToggleFlight(PlayerToggleFlightEvent event) { + Player player = event.getPlayer(); + if (player.getGameMode() != GameMode.ADVENTURE) + return; + + event.setCancelled(true); + player.setAllowFlight(false); + player.setFlying(false); + + Vector direction = player.getLocation().getDirection(); + direction.setX(direction.getX() * 1.4); + direction.setY(direction.getY() * 0.7); + direction.setZ(direction.getZ() * 1.4); + + player.setVelocity(direction.add(new Vector(0, 1.2, 0))); + player.playSound(player.getLocation(), Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, 1.0F, 1.0F); + } + + @EventHandler + public void handlePlayerMove(PlayerMoveEvent event) { + Player player = event.getPlayer(); + if(player.getGameMode() != GameMode.ADVENTURE) + return; + + if(player.getLocation().add(0, -1, 0).getBlock().getType() == Material.AIR) + return; + + player.setAllowFlight(true); + player.setFlying(false); } }