From a1432ad78253ce796e9ef378da6989a6848d2a82 Mon Sep 17 00:00:00 2001 From: Matheus Date: Sat, 15 Jun 2024 00:06:42 -0400 Subject: [PATCH] fixes + uploads v2 --- pom.xml | 5 - .../thatkawaiisam/assemble/Assemble.java | 115 +++++++ .../assemble/AssembleAdapter.java | 24 ++ .../thatkawaiisam/assemble/AssembleBoard.java | 130 ++++++++ .../assemble/AssembleBoardEntry.java | 91 ++++++ .../assemble/AssembleException.java | 14 + .../assemble/AssembleListener.java | 57 ++++ .../thatkawaiisam/assemble/AssembleStyle.java | 38 +++ .../assemble/AssembleThread.java | 127 ++++++++ .../thatkawaiisam/assemble/AssembleUtils.java | 35 ++ .../events/AssembleBoardCreateEvent.java | 31 ++ .../events/AssembleBoardCreatedEvent.java | 30 ++ .../events/AssembleBoardDestroyEvent.java | 31 ++ .../java/land/battle/practice/Practice.java | 5 +- .../battle/practice/PracticeConstants.java | 3 +- .../land/battle/practice/arena/Arena.java | 1 + .../battle/practice/board/BoardAdapter.java | 56 ++-- .../practice/listeners/EntityListener.java | 1 + .../practice/listeners/MovementListener.java | 1 + .../practice/listeners/PlayerListener.java | 101 ++++-- .../battle/practice/menu/duel/DuelMenu.java | 40 +-- .../land/battle/practice/util/BlockCheck.java | 302 ++++++++++++++++++ 22 files changed, 1157 insertions(+), 81 deletions(-) create mode 100644 src/main/java/io/github/thatkawaiisam/assemble/Assemble.java create mode 100644 src/main/java/io/github/thatkawaiisam/assemble/AssembleAdapter.java create mode 100644 src/main/java/io/github/thatkawaiisam/assemble/AssembleBoard.java create mode 100644 src/main/java/io/github/thatkawaiisam/assemble/AssembleBoardEntry.java create mode 100644 src/main/java/io/github/thatkawaiisam/assemble/AssembleException.java create mode 100644 src/main/java/io/github/thatkawaiisam/assemble/AssembleListener.java create mode 100644 src/main/java/io/github/thatkawaiisam/assemble/AssembleStyle.java create mode 100644 src/main/java/io/github/thatkawaiisam/assemble/AssembleThread.java create mode 100644 src/main/java/io/github/thatkawaiisam/assemble/AssembleUtils.java create mode 100644 src/main/java/io/github/thatkawaiisam/assemble/events/AssembleBoardCreateEvent.java create mode 100644 src/main/java/io/github/thatkawaiisam/assemble/events/AssembleBoardCreatedEvent.java create mode 100644 src/main/java/io/github/thatkawaiisam/assemble/events/AssembleBoardDestroyEvent.java create mode 100644 src/main/java/land/battle/practice/util/BlockCheck.java diff --git a/pom.xml b/pom.xml index 45105d2..e8c6f8f 100644 --- a/pom.xml +++ b/pom.xml @@ -87,11 +87,6 @@ gson 2.8.7 - - com.github.NoSequel - ScoreboardAPI - d86c2c6d87 - com.sk89q worldedit diff --git a/src/main/java/io/github/thatkawaiisam/assemble/Assemble.java b/src/main/java/io/github/thatkawaiisam/assemble/Assemble.java new file mode 100644 index 0000000..499f94a --- /dev/null +++ b/src/main/java/io/github/thatkawaiisam/assemble/Assemble.java @@ -0,0 +1,115 @@ +package io.github.thatkawaiisam.assemble; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import io.github.thatkawaiisam.assemble.events.AssembleBoardCreateEvent; +import lombok.Getter; +import lombok.Setter; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.plugin.java.JavaPlugin; + +@Getter @Setter +public class Assemble { + + private final JavaPlugin plugin; + + private AssembleAdapter adapter; + private AssembleThread thread; + private AssembleListener listeners; + private AssembleStyle assembleStyle = AssembleStyle.MODERN; + + private Map boards; + + private long ticks = 2; + private boolean hook = false, debugMode = true, callEvents = true; + + private final ChatColor[] chatColorCache = ChatColor.values(); + + /** + * Assemble. + * + * @param plugin instance. + * @param adapter that is being provided. + */ + public Assemble(JavaPlugin plugin, AssembleAdapter adapter) { + if (plugin == null) { + throw new RuntimeException("Assemble can not be instantiated without a plugin instance!"); + } + + this.plugin = plugin; + this.adapter = adapter; + this.boards = new ConcurrentHashMap<>(); + + this.setup(); + } + + /** + * Setup Assemble. + */ + public void setup() { + // Register Events. + this.listeners = new AssembleListener(this); + this.plugin.getServer().getPluginManager().registerEvents(listeners, this.plugin); + + // Ensure that the thread has stopped running. + if (this.thread != null) { + this.thread.stop(); + this.thread = null; + } + + // Register new boards for existing online players. + for (Player player : this.getPlugin().getServer().getOnlinePlayers()) { + + // Call Events if enabled. + if (this.isCallEvents()) { + AssembleBoardCreateEvent createEvent = new AssembleBoardCreateEvent(player); + + Bukkit.getPluginManager().callEvent(createEvent); + if (createEvent.isCancelled()) { + continue; + } + } + + getBoards().putIfAbsent(player.getUniqueId(), new AssembleBoard(player, this)); + } + + // Start Thread. + this.thread = new AssembleThread(this); + } + + /** + * Cleanup Assemble. + */ + public void cleanup() { + // Stop thread. + if (this.thread != null) { + this.thread.stop(); + this.thread = null; + } + + // Unregister listeners. + if (listeners != null) { + HandlerList.unregisterAll(listeners); + listeners = null; + } + + // Destroy player scoreboards. + for (UUID uuid : getBoards().keySet()) { + Player player = Bukkit.getPlayer(uuid); + + if (player == null || !player.isOnline()) { + continue; + } + + getBoards().remove(uuid); + player.setScoreboard(Bukkit.getScoreboardManager().getNewScoreboard()); + } + } + +} diff --git a/src/main/java/io/github/thatkawaiisam/assemble/AssembleAdapter.java b/src/main/java/io/github/thatkawaiisam/assemble/AssembleAdapter.java new file mode 100644 index 0000000..5288854 --- /dev/null +++ b/src/main/java/io/github/thatkawaiisam/assemble/AssembleAdapter.java @@ -0,0 +1,24 @@ +package io.github.thatkawaiisam.assemble; + +import java.util.List; +import org.bukkit.entity.Player; + +public interface AssembleAdapter { + + /** + * Get's the scoreboard title. + * + * @param player who's title is being displayed. + * @return title. + */ + String getTitle(Player player); + + /** + * Get's the scoreboard lines. + * + * @param player who's lines are being displayed. + * @return lines. + */ + List getLines(Player player); + +} diff --git a/src/main/java/io/github/thatkawaiisam/assemble/AssembleBoard.java b/src/main/java/io/github/thatkawaiisam/assemble/AssembleBoard.java new file mode 100644 index 0000000..2357c60 --- /dev/null +++ b/src/main/java/io/github/thatkawaiisam/assemble/AssembleBoard.java @@ -0,0 +1,130 @@ +package io.github.thatkawaiisam.assemble; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import io.github.thatkawaiisam.assemble.events.AssembleBoardCreatedEvent; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.scoreboard.DisplaySlot; +import org.bukkit.scoreboard.Objective; +import org.bukkit.scoreboard.Scoreboard; + +@Getter +public class AssembleBoard { + + private final Assemble assemble; + + private final List entries = new ArrayList<>(); + private final List identifiers = new ArrayList<>(); + + private final UUID uuid; + + /** + * Assemble Board. + * + * @param player that the board belongs to. + * @param assemble instance. + */ + public AssembleBoard(Player player, Assemble assemble) { + this.uuid = player.getUniqueId(); + this.assemble = assemble; + this.setup(player); + } + + /** + * Get's a player's bukkit scoreboard. + * + * @return either existing scoreboard or new scoreboard. + */ + public Scoreboard getScoreboard() { + Player player = Bukkit.getPlayer(getUuid()); + if (getAssemble().isHook() || player.getScoreboard() != Bukkit.getScoreboardManager().getMainScoreboard()) { + return player.getScoreboard(); + } else { + return Bukkit.getScoreboardManager().getNewScoreboard(); + } + } + + /** + * Get's the player's scoreboard objective. + * + * @return either existing objecting or new objective. + */ + public Objective getObjective() { + Scoreboard scoreboard = getScoreboard(); + if (scoreboard.getObjective("Assemble") == null) { + Objective objective = scoreboard.registerNewObjective("Assemble", "dummy"); + objective.setDisplaySlot(DisplaySlot.SIDEBAR); + objective.setDisplayName(getAssemble().getAdapter().getTitle(Bukkit.getPlayer(getUuid()))); + return objective; + } else { + return scoreboard.getObjective("Assemble"); + } + } + + /** + * Setup the board. + * + * @param player who's board to setup. + */ + private void setup(Player player) { + Scoreboard scoreboard = getScoreboard(); + player.setScoreboard(scoreboard); + getObjective(); + + // Call Events if enabled. + if (assemble.isCallEvents()) { + AssembleBoardCreatedEvent createdEvent = new AssembleBoardCreatedEvent(this); + Bukkit.getPluginManager().callEvent(createdEvent); + } + } + + /** + * Get the board entry at a specific position. + * + * @param pos to find entry. + * @return entry if it isn't out of range. + */ + public AssembleBoardEntry getEntryAtPosition(int pos) { + return pos >= this.entries.size() ? null : this.entries.get(pos); + } + + /** + * Get the unique identifier for position in scoreboard. + * + * @param position for identifier. + * @return unique identifier. + */ + public String getUniqueIdentifier(int position) { + String identifier = getRandomChatColor(position) + ChatColor.WHITE; + + while (this.identifiers.contains(identifier)) { + identifier = identifier + getRandomChatColor(position) + ChatColor.WHITE; + } + + // This is rare, but just in case, make the method recursive + if (identifier.length() > 16) { + return this.getUniqueIdentifier(position); + } + + // Add our identifier to the list so there are no duplicates + this.identifiers.add(identifier); + + return identifier; + } + + /** + * Gets a ChatColor based off the position in the collection. + * + * @param position of entry. + * @return ChatColor adjacent to position. + */ + private String getRandomChatColor(int position) { + return assemble.getChatColorCache()[position].toString(); + } + +} diff --git a/src/main/java/io/github/thatkawaiisam/assemble/AssembleBoardEntry.java b/src/main/java/io/github/thatkawaiisam/assemble/AssembleBoardEntry.java new file mode 100644 index 0000000..5e792f7 --- /dev/null +++ b/src/main/java/io/github/thatkawaiisam/assemble/AssembleBoardEntry.java @@ -0,0 +1,91 @@ +package io.github.thatkawaiisam.assemble; + +import org.bukkit.scoreboard.Scoreboard; +import org.bukkit.scoreboard.Team; + +import lombok.Setter; + +public class AssembleBoardEntry { + + private final AssembleBoard board; + + private Team team; + @Setter + private String text, identifier; + + /** + * Assemble Board Entry + * + * @param board that entry belongs to. + * @param text of entry. + * @param position of entry. + */ + public AssembleBoardEntry(AssembleBoard board, String text, int position) { + this.board = board; + this.text = text; + this.identifier = this.board.getUniqueIdentifier(position); + + this.setup(); + } + + /** + * Setup Board Entry. + */ + public void setup() { + final Scoreboard scoreboard = this.board.getScoreboard(); + + if (scoreboard == null) { + return; + } + + String teamName = this.identifier; + + // This shouldn't happen, but just in case. + if (teamName.length() > 16) { + teamName = teamName.substring(0, 16); + } + + Team team = scoreboard.getTeam(teamName); + + // Register the team if it does not exist. + if (team == null) { + team = scoreboard.registerNewTeam(teamName); + } + + // Add the entry to the team. + if (!team.getEntries().contains(this.identifier)) { + team.addEntry(this.identifier); + } + + // Add the entry if it does not exist. + if (!this.board.getEntries().contains(this)) { + this.board.getEntries().add(this); + } + + this.team = team; + } + + /** + * Send Board Entry Update. + * + * @param position of entry. + */ + public void send(int position) { + // Set Prefix & Suffix. + String[] split = AssembleUtils.splitTeamText(text); + this.team.setPrefix(split[0]); + this.team.setSuffix(split[1]); + + // Set the score + this.board.getObjective().getScore(this.identifier).setScore(position); + } + + /** + * Remove Board Entry from Board. + */ + public void remove() { + this.board.getIdentifiers().remove(this.identifier); + this.board.getScoreboard().resetScores(this.identifier); + } + +} diff --git a/src/main/java/io/github/thatkawaiisam/assemble/AssembleException.java b/src/main/java/io/github/thatkawaiisam/assemble/AssembleException.java new file mode 100644 index 0000000..83c0e0c --- /dev/null +++ b/src/main/java/io/github/thatkawaiisam/assemble/AssembleException.java @@ -0,0 +1,14 @@ +package io.github.thatkawaiisam.assemble; + +public class AssembleException extends RuntimeException { + + /** + * Assemble Exception. + * + * @param message attributed to exception. + */ + public AssembleException(String message) { + super(message); + } + +} diff --git a/src/main/java/io/github/thatkawaiisam/assemble/AssembleListener.java b/src/main/java/io/github/thatkawaiisam/assemble/AssembleListener.java new file mode 100644 index 0000000..9d98a98 --- /dev/null +++ b/src/main/java/io/github/thatkawaiisam/assemble/AssembleListener.java @@ -0,0 +1,57 @@ +package io.github.thatkawaiisam.assemble; + +import io.github.thatkawaiisam.assemble.events.AssembleBoardCreateEvent; +import io.github.thatkawaiisam.assemble.events.AssembleBoardDestroyEvent; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +@Getter +public class AssembleListener implements Listener { + + private final Assemble assemble; + + /** + * Assemble Listener. + * + * @param assemble instance. + */ + public AssembleListener(Assemble assemble) { + this.assemble = assemble; + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + // Call Events if enabled. + if (assemble.isCallEvents()) { + AssembleBoardCreateEvent createEvent = new AssembleBoardCreateEvent(event.getPlayer()); + + Bukkit.getPluginManager().callEvent(createEvent); + if (createEvent.isCancelled()) { + return; + } + } + + getAssemble().getBoards().put(event.getPlayer().getUniqueId(), new AssembleBoard(event.getPlayer(), getAssemble())); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + // Call Events if enabled. + if (assemble.isCallEvents()) { + AssembleBoardDestroyEvent destroyEvent = new AssembleBoardDestroyEvent(event.getPlayer()); + + Bukkit.getPluginManager().callEvent(destroyEvent); + if (destroyEvent.isCancelled()) { + return; + } + } + + getAssemble().getBoards().remove(event.getPlayer().getUniqueId()); + event.getPlayer().setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard()); + } + +} diff --git a/src/main/java/io/github/thatkawaiisam/assemble/AssembleStyle.java b/src/main/java/io/github/thatkawaiisam/assemble/AssembleStyle.java new file mode 100644 index 0000000..b5b53e3 --- /dev/null +++ b/src/main/java/io/github/thatkawaiisam/assemble/AssembleStyle.java @@ -0,0 +1,38 @@ +package io.github.thatkawaiisam.assemble; + +import lombok.Getter; + +@Getter +public enum AssembleStyle { + + KOHI(true, 15), VIPER(true, -1), MODERN(false, 1), CUSTOM(false, 0); + + private boolean descending; + private int startNumber; + + /** + * Assemble Style. + * + * @param descending whether the positions are going down or up. + * @param startNumber from where to loop from. + */ + AssembleStyle(boolean descending, int startNumber) { + this.descending = descending; + this.startNumber = startNumber; + } + + public AssembleStyle reverse() { + return descending(!this.descending); + } + + public AssembleStyle descending(boolean descending) { + this.descending = descending; + return this; + } + + public AssembleStyle startNumber(int startNumber) { + this.startNumber = startNumber; + return this; + } + +} diff --git a/src/main/java/io/github/thatkawaiisam/assemble/AssembleThread.java b/src/main/java/io/github/thatkawaiisam/assemble/AssembleThread.java new file mode 100644 index 0000000..2c6f933 --- /dev/null +++ b/src/main/java/io/github/thatkawaiisam/assemble/AssembleThread.java @@ -0,0 +1,127 @@ +package io.github.thatkawaiisam.assemble; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.scoreboard.Objective; +import org.bukkit.scoreboard.Scoreboard; + +import java.util.Collections; +import java.util.List; + +public class AssembleThread extends Thread { + + private final Assemble assemble; + + /** + * Assemble Thread. + * + * @param assemble instance. + */ + AssembleThread(Assemble assemble) { + this.assemble = assemble; + this.start(); + } + + @Override + public void run() { + while(true) { + try { + tick(); + sleep(assemble.getTicks() * 50); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** + * Tick logic for thread. + */ + private void tick() { + for (Player player : this.assemble.getPlugin().getServer().getOnlinePlayers()) { + try { + AssembleBoard board = this.assemble.getBoards().get(player.getUniqueId()); + + // This shouldn't happen, but just in case. + if (board == null) { + continue; + } + + Scoreboard scoreboard = board.getScoreboard(); + Objective objective = board.getObjective(); + + if (scoreboard == null || objective == null) { + continue; + } + + // Just make a variable so we don't have to + // process the same thing twice. + String title = ChatColor.translateAlternateColorCodes('&', this.assemble.getAdapter().getTitle(player)); + + // Update the title if needed. + if (!objective.getDisplayName().equals(title)) { + objective.setDisplayName(title); + } + + List newLines = this.assemble.getAdapter().getLines(player); + + // Allow adapter to return null/empty list to display nothing. + if (newLines == null || newLines.isEmpty()) { + board.getEntries().forEach(AssembleBoardEntry::remove); + board.getEntries().clear(); + } else { + if (newLines.size() > 15) { + newLines = newLines.subList(0, 15); + } + + // Reverse the lines because scoreboard scores are in descending order. + if (!this.assemble.getAssembleStyle().isDescending()) { + Collections.reverse(newLines); + } + + // Remove excessive amount of board entries. + if (board.getEntries().size() > newLines.size()) { + for (int i = newLines.size(); i < board.getEntries().size(); i++) { + AssembleBoardEntry entry = board.getEntryAtPosition(i); + + if (entry != null) { + entry.remove(); + } + } + } + + // Update existing entries / add new entries. + int cache = this.assemble.getAssembleStyle().getStartNumber(); + for (int i = 0; i < newLines.size(); i++) { + AssembleBoardEntry entry = board.getEntryAtPosition(i); + + // Translate any colors. + String line = ChatColor.translateAlternateColorCodes('&', newLines.get(i)); + + // If the entry is null, just create a new one. + // Creating a new AssembleBoardEntry instance will add + // itself to the provided board's entries list. + if (entry == null) { + entry = new AssembleBoardEntry(board, line, i); + } + + // Update text, setup the team, and update the display values. + entry.setText(line); + entry.setup(); + entry.send( + this.assemble.getAssembleStyle().isDescending() ? cache-- : cache++ + ); + } + } + + if (player.getScoreboard() != scoreboard && !assemble.isHook()) { + player.setScoreboard(scoreboard); + } + } catch(Exception e) { + e.printStackTrace(); + throw new AssembleException("There was an error updating " + player.getName() + "'s scoreboard."); + } + } + } + +} diff --git a/src/main/java/io/github/thatkawaiisam/assemble/AssembleUtils.java b/src/main/java/io/github/thatkawaiisam/assemble/AssembleUtils.java new file mode 100644 index 0000000..f7dd1b4 --- /dev/null +++ b/src/main/java/io/github/thatkawaiisam/assemble/AssembleUtils.java @@ -0,0 +1,35 @@ +package io.github.thatkawaiisam.assemble; + +import org.bukkit.ChatColor; + +public class AssembleUtils { + + public static String[] splitTeamText(String input) { + final int inputLength = input.length(); + if (inputLength > 16) { + // Make the prefix the first 16 characters of our text + String prefix = input.substring(0, 16); + + // Get the last index of the color char in the prefix + final int lastColorIndex = prefix.lastIndexOf(ChatColor.COLOR_CHAR); + + String suffix; + + if (lastColorIndex >= 14) { + prefix = prefix.substring(0, lastColorIndex); + suffix = ChatColor.getLastColors(input.substring(0, 17)) + input.substring(lastColorIndex + 2); + } else { + suffix = ChatColor.getLastColors(prefix) + input.substring(16); + } + + if (suffix.length() > 16) { + suffix = suffix.substring(0, 16); + } + + return new String[] {prefix, suffix}; + } else { + return new String[] {input, ""}; + } + } + +} diff --git a/src/main/java/io/github/thatkawaiisam/assemble/events/AssembleBoardCreateEvent.java b/src/main/java/io/github/thatkawaiisam/assemble/events/AssembleBoardCreateEvent.java new file mode 100644 index 0000000..8ebe3c1 --- /dev/null +++ b/src/main/java/io/github/thatkawaiisam/assemble/events/AssembleBoardCreateEvent.java @@ -0,0 +1,31 @@ +package io.github.thatkawaiisam.assemble.events; + +import lombok.Getter; +import lombok.Setter; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +@Getter @Setter +public class AssembleBoardCreateEvent extends Event implements Cancellable { + + @Getter public static HandlerList handlerList = new HandlerList(); + + private Player player; + private boolean cancelled = false; + + /** + * Assemble Board Create Event. + * + * @param player that the board is being created for. + */ + public AssembleBoardCreateEvent(Player player) { + this.player = player; + } + + @Override + public HandlerList getHandlers() { + return handlerList; + } +} diff --git a/src/main/java/io/github/thatkawaiisam/assemble/events/AssembleBoardCreatedEvent.java b/src/main/java/io/github/thatkawaiisam/assemble/events/AssembleBoardCreatedEvent.java new file mode 100644 index 0000000..2f7341f --- /dev/null +++ b/src/main/java/io/github/thatkawaiisam/assemble/events/AssembleBoardCreatedEvent.java @@ -0,0 +1,30 @@ +package io.github.thatkawaiisam.assemble.events; + +import io.github.thatkawaiisam.assemble.AssembleBoard; +import lombok.Getter; +import lombok.Setter; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +@Getter @Setter +public class AssembleBoardCreatedEvent extends Event { + + @Getter public static HandlerList handlerList = new HandlerList(); + + private boolean cancelled = false; + private final AssembleBoard board; + + /** + * Assemble Board Created Event. + * + * @param board of player. + */ + public AssembleBoardCreatedEvent(AssembleBoard board) { + this.board = board; + } + + @Override + public HandlerList getHandlers() { + return handlerList; + } +} diff --git a/src/main/java/io/github/thatkawaiisam/assemble/events/AssembleBoardDestroyEvent.java b/src/main/java/io/github/thatkawaiisam/assemble/events/AssembleBoardDestroyEvent.java new file mode 100644 index 0000000..3f68628 --- /dev/null +++ b/src/main/java/io/github/thatkawaiisam/assemble/events/AssembleBoardDestroyEvent.java @@ -0,0 +1,31 @@ +package io.github.thatkawaiisam.assemble.events; + +import lombok.Getter; +import lombok.Setter; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +@Getter @Setter +public class AssembleBoardDestroyEvent extends Event implements Cancellable { + + @Getter public static HandlerList handlerList = new HandlerList(); + + private Player player; + private boolean cancelled = false; + + /** + * Assemble Board Destroy Event. + * + * @param player who's board got destroyed. + */ + public AssembleBoardDestroyEvent(Player player) { + this.player = player; + } + + @Override + public HandlerList getHandlers() { + return handlerList; + } +} diff --git a/src/main/java/land/battle/practice/Practice.java b/src/main/java/land/battle/practice/Practice.java index 7ee5870..3de7dd8 100644 --- a/src/main/java/land/battle/practice/Practice.java +++ b/src/main/java/land/battle/practice/Practice.java @@ -7,7 +7,7 @@ import com.solexgames.lib.commons.command.context.CommonsPlayer; import com.solexgames.lib.processor.config.ConfigFactory; import com.solexgames.shop.Shop; import com.solexgames.shop.category.impl.configurable.KillEffectShopCategory; -import io.github.nosequel.scoreboard.ScoreboardHandler; +import io.github.thatkawaiisam.assemble.Assemble; import land.battle.practice.arena.Arena; import land.battle.practice.board.BoardAdapter; import land.battle.practice.commands.*; @@ -115,7 +115,8 @@ public class Practice extends ExtendedJavaPlugin { this.loadingString.equals(".") ? ".." : this.loadingString.equals("..") ? "..." : ".", 10L, 10L); - new ScoreboardHandler(this, new BoardAdapter(), 2L); + Assemble assemble = new Assemble(this, new BoardAdapter()); + assemble.setTicks(2); CorePlugin.getInstance().addNewSettingHandler(new PracticeSettingsImpl()); diff --git a/src/main/java/land/battle/practice/PracticeConstants.java b/src/main/java/land/battle/practice/PracticeConstants.java index 028a205..f0f9273 100644 --- a/src/main/java/land/battle/practice/PracticeConstants.java +++ b/src/main/java/land/battle/practice/PracticeConstants.java @@ -6,7 +6,6 @@ import land.battle.practice.player.PlayerData; import land.battle.practice.state.PlayerStateAdapter; import land.battle.practice.state.impl.*; import land.battle.practice.util.CC; -import io.github.nosequel.scoreboard.element.ScoreboardElement; import lombok.experimental.UtilityClass; import org.bukkit.ChatColor; import org.bukkit.entity.Player; @@ -58,7 +57,7 @@ public class PracticeConstants { BOARD_ADAPTERS.put("editor", new EditorBoardAdapter()); } - public static void handleAdapter(String id, ScoreboardElement element, Player player, PlayerData playerData, Party party) { + public static void handleAdapter(String id, List element, Player player, PlayerData playerData, Party party) { final PlayerStateAdapter adapter = PracticeConstants.BOARD_ADAPTERS.get(id); if (adapter != null) { diff --git a/src/main/java/land/battle/practice/arena/Arena.java b/src/main/java/land/battle/practice/arena/Arena.java index 36c8bb0..00c5013 100644 --- a/src/main/java/land/battle/practice/arena/Arena.java +++ b/src/main/java/land/battle/practice/arena/Arena.java @@ -3,6 +3,7 @@ package land.battle.practice.arena; import land.battle.practice.arena.type.StandaloneArena; import land.battle.practice.flags.Flag; import land.battle.practice.location.impl.impl.AsyncLocation; +import land.battle.practice.util.cuboid.Cuboid; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/land/battle/practice/board/BoardAdapter.java b/src/main/java/land/battle/practice/board/BoardAdapter.java index 6e1b33e..2ec1d88 100644 --- a/src/main/java/land/battle/practice/board/BoardAdapter.java +++ b/src/main/java/land/battle/practice/board/BoardAdapter.java @@ -3,6 +3,7 @@ package land.battle.practice.board; import com.solexgames.core.CorePlugin; import com.solexgames.core.player.PotPlayer; import com.solexgames.core.util.Color; +import io.github.thatkawaiisam.assemble.AssembleAdapter; import land.battle.practice.Practice; import land.battle.practice.PracticeConstants; import land.battle.practice.party.Party; @@ -10,77 +11,80 @@ import land.battle.practice.player.PlayerData; import land.battle.practice.player.PlayerState; import land.battle.practice.util.Animation; import land.battle.practice.util.CC; -import io.github.nosequel.scoreboard.element.ScoreboardElement; -import io.github.nosequel.scoreboard.element.ScoreboardElementHandler; import org.bukkit.entity.Player; +import java.util.ArrayList; +import java.util.List; + /** * @author BattleLand Team * @since 8/14/2021 */ -public class BoardAdapter implements ScoreboardElementHandler { +public class BoardAdapter implements AssembleAdapter { + + public boolean isState(PlayerData playerData, PlayerState playerState) { + return playerData.getPlayerState().equals(playerState); + } @Override - public ScoreboardElement getElement(Player player) { - final ScoreboardElement element = new ScoreboardElement(); + public String getTitle(Player player) { + return CC.GOLD + CC.BOLD + (!Practice.getInstance().isHolanda() ? "Battle " + CC.GRAY + "⏐" + CC.WHITE + " Practice" : "Practice"); + } + @Override + public List getLines(Player player) { + List lines = new ArrayList<>(); final PlayerData playerData = Practice.getInstance().getPlayerManager() .getPlayerData(player.getUniqueId()); - element.setTitle(CC.GOLD + CC.BOLD + (!Practice.getInstance().isHolanda() ? "Battle " + CC.GRAY + "⏐" + CC.WHITE + " Practice" : "Practice")); - if (playerData == null || !playerData.getOptions().isScoreboardEnabled()) { - return element; + return null; } final Party party = Practice.getInstance().getPartyManager().getParty(player.getUniqueId()); switch (playerData.getOptions().getScoreboardStyle()) { case MODERN: - element.add(""); + lines.add(""); break; case OLD: - element.add(CC.SB_LINE); + lines.add(CC.SB_LINE); break; } final boolean queued = this.isState(playerData, PlayerState.QUEUE); if (this.isState(playerData, PlayerState.SPAWN) || queued) { - PracticeConstants.handleAdapter("spawn", element, player, playerData, party); + PracticeConstants.handleAdapter("spawn", lines, player, playerData, party); if (queued) { - PracticeConstants.handleAdapter("queue", element, player, playerData, party); + PracticeConstants.handleAdapter("queue", lines, player, playerData, party); } if (party != null) { - PracticeConstants.handleAdapter("party", element, player, playerData, party); + PracticeConstants.handleAdapter("party", lines, player, playerData, party); } } else if (this.isState(playerData, PlayerState.FIGHTING)) { - PracticeConstants.handleAdapter("match", element, player, playerData, party); + PracticeConstants.handleAdapter("match", lines, player, playerData, party); } else if (this.isState(playerData, PlayerState.SPECTATING)) { - PracticeConstants.handleAdapter("spectator", element, player, playerData, party); + PracticeConstants.handleAdapter("spectator", lines, player, playerData, party); } else if (this.isState(playerData, PlayerState.EDITING)) { - PracticeConstants.handleAdapter("editor", element, player, playerData, party); + PracticeConstants.handleAdapter("editor", lines, player, playerData, party); } switch (playerData.getOptions().getScoreboardStyle()) { case MODERN: - element.add(""); - element.add(CC.GOLD + (Practice.getInstance().isHolanda() ? CC.translate(Animation.getScoreboardFooter()) : "battle.land") + " " + CC.GRAY + " " + CC.GRAY + " "); + lines.add(""); + lines.add(CC.GOLD + (Practice.getInstance().isHolanda() ? CC.translate(Animation.getScoreboardFooter()) : "battle.land") + " " + CC.GRAY + " " + CC.GRAY + " "); break; case OLD: - element.add(""); - element.add(CC.GOLD + (Practice.getInstance().isHolanda() ? CC.translate(Animation.getScoreboardFooter()) : "battle.land")); - element.add(CC.SB_LINE); + lines.add(""); + lines.add(CC.GOLD + (Practice.getInstance().isHolanda() ? CC.translate(Animation.getScoreboardFooter()) : "battle.land")); + lines.add(CC.SB_LINE); break; } - return element; - } - - public boolean isState(PlayerData playerData, PlayerState playerState) { - return playerData.getPlayerState().equals(playerState); + return lines; } } diff --git a/src/main/java/land/battle/practice/listeners/EntityListener.java b/src/main/java/land/battle/practice/listeners/EntityListener.java index c050539..f55e109 100644 --- a/src/main/java/land/battle/practice/listeners/EntityListener.java +++ b/src/main/java/land/battle/practice/listeners/EntityListener.java @@ -79,6 +79,7 @@ public class EntityListener implements Listener { @EventHandler public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { + if (!(event.getEntity() instanceof Player || event.getDamager() instanceof Player)) return; Player whoWasHit = (Player)event.getEntity(); Player whoHit = (Player)event.getDamager(); diff --git a/src/main/java/land/battle/practice/listeners/MovementListener.java b/src/main/java/land/battle/practice/listeners/MovementListener.java index 06c8cba..418c268 100644 --- a/src/main/java/land/battle/practice/listeners/MovementListener.java +++ b/src/main/java/land/battle/practice/listeners/MovementListener.java @@ -8,6 +8,7 @@ import land.battle.practice.player.PlayerData; import land.battle.practice.player.PlayerState; import land.battle.practice.util.BlockUtil; import io.papermc.lib.PaperLib; +import land.battle.practice.util.cuboid.Cuboid; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.entity.Player; diff --git a/src/main/java/land/battle/practice/listeners/PlayerListener.java b/src/main/java/land/battle/practice/listeners/PlayerListener.java index b76b36b..240ccb7 100644 --- a/src/main/java/land/battle/practice/listeners/PlayerListener.java +++ b/src/main/java/land/battle/practice/listeners/PlayerListener.java @@ -6,6 +6,8 @@ import com.solexgames.core.player.PotPlayer; import com.solexgames.core.player.prefixes.Prefix; import com.solexgames.core.util.Color; import com.solexgames.core.util.StringUtil; +import com.solexgames.shop.menu.ShopCategoryMenu; +import io.papermc.lib.PaperLib; import land.battle.practice.Practice; import land.battle.practice.PracticeConstants; import land.battle.practice.PracticeServerType; @@ -15,7 +17,6 @@ import land.battle.practice.kit.Kit; import land.battle.practice.kit.PlayerKit; import land.battle.practice.match.Match; import land.battle.practice.match.MatchState; -import land.battle.practice.menu.EventHostMenu; import land.battle.practice.menu.JoinQueueMenu; import land.battle.practice.menu.LeaderboardsMenu; import land.battle.practice.menu.SpectateMenu; @@ -27,19 +28,15 @@ import land.battle.practice.player.PlayerData; import land.battle.practice.player.PlayerState; import land.battle.practice.queue.QueueType; import land.battle.practice.settings.PracticeSettingsMenu; +import land.battle.practice.util.BlockCheck; import land.battle.practice.util.CC; -import land.battle.practice.util.DeathUtils; import land.battle.practice.util.PlayerUtil; -import com.solexgames.shop.menu.ShopCategoryMenu; -import io.papermc.lib.PaperLib; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.GameMode; -import org.bukkit.Material; +import org.bukkit.*; import org.bukkit.block.Sign; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.entity.*; import org.bukkit.event.inventory.CraftItemEvent; @@ -49,10 +46,8 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; -import org.bukkit.util.Vector; -import java.util.Map; -import java.util.UUID; +import java.util.*; public class PlayerListener implements Listener { @@ -140,27 +135,27 @@ public class PlayerListener implements Listener { switch (serverType) { case PROD_WHITELISTED: Practice.getInstance().fetchNitroReward(player).whenComplete((aBoolean, throwable) -> { - if (throwable != null) { - throwable.printStackTrace(); - } + if (throwable != null) { + throwable.printStackTrace(); + } - final PotPlayer potPlayer = CorePlugin.getInstance() - .getPlayerManager().getPlayer(player); + final PotPlayer potPlayer = CorePlugin.getInstance() + .getPlayerManager().getPlayer(player); - if (aBoolean && !potPlayer.getAllPrefixes().contains("Booster")) { - final Prefix prefix = Prefix.getByName("Booster"); + if (aBoolean && !potPlayer.getAllPrefixes().contains("Booster")) { + final Prefix prefix = Prefix.getByName("Booster"); - if (prefix != null) { - potPlayer.getAllPrefixes().add(prefix.getName()); - potPlayer.saveWithoutRemove(); + if (prefix != null) { + potPlayer.getAllPrefixes().add(prefix.getName()); + potPlayer.saveWithoutRemove(); - player.sendMessage(ChatColor.GREEN + "You've been given access to the " + Color.translate(prefix.getDisplayName()) + ChatColor.GREEN + " prefix."); - } + player.sendMessage(ChatColor.GREEN + "You've been given access to the " + Color.translate(prefix.getDisplayName()) + ChatColor.GREEN + " prefix."); + } - CorePlugin.getInstance().getJedisManager().runCommand(jedis -> { - jedis.hdel(PracticeConstants.JEDIS_DISCORD_REWARD_CATEGORY, player.getUniqueId().toString()); - }); - } + CorePlugin.getInstance().getJedisManager().runCommand(jedis -> { + jedis.hdel(PracticeConstants.JEDIS_DISCORD_REWARD_CATEGORY, player.getUniqueId().toString()); + }); + } }); case PROD_RELEASE_DAY: if (!PracticeConstants.CHANGELOG.isEmpty()) { @@ -301,7 +296,7 @@ public class PlayerListener implements Listener { } } if (event.getClickedBlock().getType() == Material.CHEST - || event.getClickedBlock().getType() == Material.ENDER_CHEST) { + || event.getClickedBlock().getType() == Material.ENDER_CHEST) { event.setCancelled(true); } } @@ -698,6 +693,56 @@ public class PlayerListener implements Listener { } } + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onEvent(PlayerTeleportEvent event) { + if (event.getCause().equals(PlayerTeleportEvent.TeleportCause.ENDER_PEARL)) { + event.getTo().setX(Math.floor(event.getTo().getX()) + 0.5f); + event.getTo().setY(Math.floor(event.getTo().getY()) + 0.5f); + event.getTo().setZ(Math.floor(event.getTo().getZ()) + 0.5f); + BlockCheck landing = new BlockCheck(event.getTo().getBlock()); + boolean cancelTeleport = true; + if ((event.getFrom().getWorld() == event.getTo().getWorld()) && (event.getFrom().distanceSquared(event.getTo()) < 32768)) { + cancelTeleport = false; + if (landing.isSafe) { + event.getTo().setY(Math.floor(event.getTo().getY()) + landing.adjustY); + } else { + cancelTeleport = true; + double xMin = Math.min(event.getFrom().getX(), event.getTo().getX()); + double xMax = Math.max(event.getFrom().getX(), event.getTo().getX()); + double yMin = Math.min(event.getFrom().getY(), event.getTo().getY()); + double yMax = Math.max(event.getFrom().getY(), event.getTo().getY()); + double zMin = Math.min(event.getFrom().getZ(), event.getTo().getZ()); + double zMax = Math.max(event.getFrom().getZ(), event.getTo().getZ()); + List locations = new ArrayList(); + for (double x = xMin; x < xMax; x++) { + for (double y = yMin; y < yMax; y++) { + for (double z = zMin; z < zMax; z++) { + locations.add(new Location(event.getTo().getWorld(), Math.floor(x) + 0.5f, Math.floor(y) + 0.5f, Math.floor(z) + 0.5f)); + } + } + } + locations.sort(Comparator.comparing(location -> event.getTo().distanceSquared(location))); + for (Location location : locations) { + BlockCheck blockCheck = new BlockCheck(location.getBlock()); + if (blockCheck.isSafe) { + location.setYaw(event.getTo().getYaw()); + location.setPitch(event.getTo().getPitch()); + location.setY(Math.floor(location.getY()) + blockCheck.adjustY); + event.setTo(location); + cancelTeleport = false; + break; + } + } + } + } + if ((cancelTeleport) || (event.getTo().equals(event.getFrom()))) { + event.setCancelled(true); + event.getPlayer().getInventory().addItem(new ItemStack(Material.ENDER_PEARL, 1)); + event.getPlayer().updateInventory(); + } + } + } + @EventHandler public void onCraft(CraftItemEvent event) { event.setCancelled(true); diff --git a/src/main/java/land/battle/practice/menu/duel/DuelMenu.java b/src/main/java/land/battle/practice/menu/duel/DuelMenu.java index 4984956..5f53c1b 100644 --- a/src/main/java/land/battle/practice/menu/duel/DuelMenu.java +++ b/src/main/java/land/battle/practice/menu/duel/DuelMenu.java @@ -23,10 +23,8 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.lang.reflect.Array; +import java.util.*; import java.util.concurrent.atomic.AtomicInteger; /** @@ -109,7 +107,7 @@ public class DuelMenu extends Menu { ) .toUpdatingButton((player1, clickType) -> { if (this.kit == null) { - player.sendMessage(CC.RED + "Voce deve selecionar o kit antes de selecionar a arena"); + player.sendMessage(CC.RED + "You must select a kit before switching to the arena inventory"); return; } @@ -117,23 +115,29 @@ public class DuelMenu extends Menu { }) ); + List lore = Practice.getInstance().isHolanda() ? Arrays.asList( + CC.GRAY + "Confirm your settings and send", + CC.GRAY + "the duel to out.", + "", + (this.arena == null || this.kit == null ? CC.RED + "[Cannot send duel right now]" : CC.YELLOW + "[Click to send duel to player]") + ) : Arrays.asList( + CC.GRAY + "Confirmar suas configuraçoes e mandar", + CC.GRAY + "o duel para ele.", + "", + (this.arena == null || this.kit == null ? CC.RED + "[Selecione antes!]" : CC.YELLOW + "[Clique para mandar o duelo]")); + buttonMap.put(50, new ItemBuilder(Material.INK_SACK) - .setDisplayName(CC.GOLD + CC.BOLD + "Confirmar Duel") - .addLore( - CC.GRAY + "Confirmar suas configuraçoes e mandar", - CC.GRAY + "o duel para ele.", - "", - (this.arena == null || this.kit == null ? CC.RED + "[Selecione antes!]" : CC.YELLOW + "[Clique para mandar o duelo]") - ) + .setDisplayName(CC.GOLD + CC.BOLD + "Confirm Duel") + .addLore(lore) .setDurability(this.arena == null || this.kit == null ? 8 : 10) .toButton((player1, clickType) -> { if (this.arena == null) { - player.sendMessage(CC.RED + "Voce deve selecionar uma arena antes de confirmar o duel."); + player.sendMessage(CC.RED + (Practice.getInstance().isHolanda() ? "You must select an arena before confirming the duel." : "Voce deve selecionar uma arena antes de confirmar o duel.")); return; } if (this.kit == null) { - player.sendMessage(CC.RED + "Voce deve selecionar um kit antes de confirmar o duel."); + player.sendMessage(CC.RED + (Practice.getInstance().isHolanda() ? "You must select a kit before confirming the duel." : "Voce deve selecionar um kit antes de confirmar o duel.")); return; } @@ -194,11 +198,11 @@ public class DuelMenu extends Menu { final List lore = new ArrayList<>(); if (arena != null && arena.getName().equals(newArena.getName())) { - lore.add(CC.GRAY + "Voce tem essa arena selecionada."); + lore.add(CC.GRAY + (Practice.getInstance().isHolanda() ? "You have this arena selected." : "Voce tem essa arena selecionada.")); lore.add(" "); } - lore.add(CC.YELLOW + "[Clique para duelar com essa arena]"); + lore.add(CC.YELLOW + (Practice.getInstance().isHolanda() ? "[Click to duel with this arena]" : "[Clique para duelar com essa arena]")); final ItemBuilder itemBuilder = new ItemBuilder(this.newArena.getIcon() == null ? Material.PAPER : this.newArena.getIcon()) .setDisplayName(Color.MAIN_COLOR + CC.BOLD + this.newArena.getName()) @@ -233,11 +237,11 @@ public class DuelMenu extends Menu { final List lore = new ArrayList<>(); if (kit != null && kit.getName().equals(queue.getName())) { - lore.add(CC.GRAY + "Voce tem esse kit selecionado."); + lore.add(CC.GRAY + (Practice.getInstance().isHolanda() ? "You have this kit selected." : "Voce tem esse kit selecionado.")); lore.add(" "); } - lore.add(CC.YELLOW + "[Clique para mandar com esse kit!]"); + lore.add(CC.YELLOW + (Practice.getInstance().isHolanda() ? "[Click to duel with this kit]" : "[Clique para mandar com esse kit!]")); final ItemBuilder itemBuilder = new ItemBuilder(this.queue.getIcon().clone()) .setDisplayName(Color.MAIN_COLOR + CC.BOLD + this.queue.getName()) diff --git a/src/main/java/land/battle/practice/util/BlockCheck.java b/src/main/java/land/battle/practice/util/BlockCheck.java new file mode 100644 index 0000000..29d23fe --- /dev/null +++ b/src/main/java/land/battle/practice/util/BlockCheck.java @@ -0,0 +1,302 @@ +package land.battle.practice.util; + +import org.bukkit.block.Block; +import org.bukkit.material.Openable; + +@SuppressWarnings("deprecation") +public class BlockCheck { + public boolean isSafe; + public double adjustY; + + public BlockCheck(Block block) { + isSafe = false; + adjustY = 0; + Block above = block.getLocation().clone().add(0, 1, 0).getBlock(); + Block below = block.getLocation().clone().add(0, -1, 0).getBlock(); + Block upTwo = block.getLocation().clone().add(0, 2, 0).getBlock(); + Block downTwo = block.getLocation().clone().add(0, -2, 0).getBlock(); + if (isSafe(block) && isSafe(above)) { + isSafe = true; + } else if (isSafe(block) && isSafe(below)) { + isSafe = true; + adjustY = -1.0f; + } else if (isSafe(block)) { + if (!isSolid(above) && (isOpenDoor(above) || isTopDoor(above))) { + isSafe = true; + } else if (!isSolid(below) && ((isTrapDoor(below) && !isTopDoor(below)) || isOpenDoor(below))) { + isSafe = true; + adjustY = -0.8125f; + } else if (!isSolid(above) && !isSolid(below) && isTopSlab(above) && (isSlab(below) && !isTopSlab(below))) { + isSafe = true; + adjustY = -0.5f; + } + } else if (isTrapDoor(block) && !isTopDoor(block) && isSafe(above)) { + isSafe = true; + adjustY = 0.1875f; + } else if (isTopDoor(block) && isSafe(below)) { + isSafe = true; + adjustY = -1.0f; + } else if (isSlab(block) && !isTopSlab(block) && isSafe(above)) { + if (isSafe(upTwo)) { + isSafe = true; + } else if (isTopSlab(upTwo) || isTopDoor(upTwo)) { + isSafe = true; + } + if (isSafe) { + adjustY = .5f; + } + } else if (isTopSlab(block) && isSafe(below)) { + if (isSafe(downTwo)) { + isSafe = true; + adjustY = -2.0f; + } else if (isSlab(downTwo) && !isTopSlab(downTwo)) { + isSafe = true; + adjustY = -1.5f; + } else if (isTrapDoor(downTwo) && !isTopDoor(downTwo)) { + isSafe = true; + adjustY = -1.8125f; + } + } + } + + public boolean isSolid(Block block) { + int type = block.getType().getId(); + switch (type) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 7: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 29: + case 34: + case 33: + case 35: + case 36: + case 41: + case 42: + case 43: + case 45: + case 46: + case 47: + case 48: + case 49: + case 52: + case 53: + case 54: + case 56: + case 57: + case 58: + case 60: + case 61: + case 62: + case 64: + case 65: + case 67: + case 71: + case 73: + case 74: + case 78: + case 79: + case 80: + case 81: + case 82: + case 84: + case 85: + case 86: + case 87: + case 88: + case 89: + case 91: + case 92: + case 93: + case 94: + case 95: + case 97: + case 98: + case 99: + case 100: + case 101: + case 102: + case 103: + case 106: + case 107: + case 108: + case 109: + case 110: + case 111: + case 112: + case 113: + case 114: + case 116: + case 117: + case 118: + case 120: + case 121: + case 122: + case 123: + case 124: + case 125: + case 127: + case 128: + case 129: + case 130: + case 133: + case 134: + case 135: + case 136: + case 137: + case 138: + case 139: + case 140: + case 144: + case 145: + case 146: + case 149: + case 150: + case 151: + case 152: + case 153: + case 154: + case 155: + case 156: + case 158: + case 159: + case 160: + case 161: + case 162: + case 163: + case 164: + case 165: + case 166: + case 168: + case 169: + case 170: + case 171: + case 172: + case 173: + case 174: + case 178: + case 179: + case 180: + case 181: + case 183: + case 184: + case 185: + case 186: + case 187: + case 188: + case 189: + case 190: + case 191: + case 192: + case 193: + case 194: + case 195: + case 196: + case 197: + case 198: + case 199: + case 200: + case 201: + case 202: + case 203: + case 204: + case 206: + case 207: + case 208: + case 210: + case 211: + case 212: + case 213: + case 214: + case 215: + case 216: + case 218: + case 219: + case 220: + case 221: + case 222: + case 223: + case 224: + case 225: + case 226: + case 227: + case 228: + case 229: + case 230: + case 231: + case 232: + case 233: + case 234: + case 235: + case 236: + case 237: + case 238: + case 239: + case 240: + case 241: + case 242: + case 243: + case 244: + case 245: + case 246: + case 247: + case 248: + case 249: + case 250: + case 251: + case 252: + case 255: + case 397: + case 355: + return true; + } + return false; + } + + private boolean isSlab(Block block) { + return block.getType().getId() == 44 || block.getType().getId() == 126 || block.getType().getId() == 182; + } + + private boolean isTrapDoor(Block block) { + return block.getType().getId() == 96 || block.getType().getId() == 167; + } + + private boolean isOpenDoor(Block block) { + return (isTrapDoor(block) && ((Openable) block.getState().getData()).isOpen()); + } + + private boolean isTopDoor(Block block) { + if (!isTrapDoor(block)) { + return false; + } + return block.getData() == 8 || block.getData() == 9 || block.getData() == 10 || block.getData() == 11; + } + + private boolean isTopSlab(Block block) { + if (!isSlab(block)) { + return false; + } + return block.getData() == 8 || block.getData() == 9 || block.getData() == 10 || block.getData() == 11 || block.getData() == 12 || block.getData() == 13 || block.getData() == 14 || block.getData() == 15; + } + + private boolean isSafe(Block block) { + return !isSolid(block) && !isSlab(block) && (!isTrapDoor(block) || isOpenDoor(block)); + } +} \ No newline at end of file