diff options
author | Tyler Murphy <tylermurphy534@gmail.com> | 2021-12-30 12:17:32 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-30 12:17:32 -0500 |
commit | 31d60d7d23715aa3f063241c0c420ea0b0bf003b (patch) | |
tree | ca43ffa540d9629f6f0faf2ab3d5e5941db0f352 /src/main/java/net/tylermurphy/hideAndSeek/game | |
parent | Merge pull request #16 from tylermurphy534/1.3.2 (diff) | |
parent | 1.3.3 rc5 (diff) | |
download | kenshinshideandseek-31d60d7d23715aa3f063241c0c420ea0b0bf003b.tar.gz kenshinshideandseek-31d60d7d23715aa3f063241c0c420ea0b0bf003b.tar.bz2 kenshinshideandseek-31d60d7d23715aa3f063241c0c420ea0b0bf003b.zip |
Merge pull request #20 from tylermurphy534/1.3.3
1.3.3
Diffstat (limited to 'src/main/java/net/tylermurphy/hideAndSeek/game')
4 files changed, 1270 insertions, 0 deletions
diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/Board.java b/src/main/java/net/tylermurphy/hideAndSeek/game/Board.java new file mode 100644 index 0000000..936f7ac --- /dev/null +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/Board.java @@ -0,0 +1,374 @@ +/* + * This file is part of Kenshins Hide and Seek + * + * Copyright (c) 2021 Tyler Murphy. + * + * Kenshins Hide and Seek free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * he Free Software Foundation version 3. + * + * Kenshins Hide and Seek is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +package net.tylermurphy.hideAndSeek.game; + +import static net.tylermurphy.hideAndSeek.configuration.Config.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import net.tylermurphy.hideAndSeek.util.Status; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.scoreboard.*; + +public class Board { + + private static final List<String> Hider = new ArrayList<>(), Seeker = new ArrayList<>(), Spectator = new ArrayList<>(); + private static final Map<String, Player> playerList = new HashMap<>(); + private static final Map<String, CustomBoard> customBoards = new HashMap<>(); + + public static boolean isPlayer(Player player) { + return playerList.containsKey(player.getName()); + } + + public static boolean isPlayer(String name){ + return playerList.containsKey(name); + } + + public static boolean isPlayer(CommandSender sender) { + return playerList.containsKey(sender.getName()); + } + + public static boolean isHider(Player player) { + return Hider.contains(player.getName()); + } + + public static boolean isSeeker(Player player) { + return Seeker.contains(player.getName()); + } + + public static boolean isSpectator(Player player) { + return Spectator.contains(player.getName()); + } + + public static int sizeHider() { + return Hider.size(); + } + + public static int sizeSeeker() { + return Seeker.size(); + } + + public static int size() { + return playerList.values().size(); + } + + public static List<Player> getHiders(){ + return Hider.stream().map(playerList::get).collect(Collectors.toList()); + } + + public static List<Player> getSeekers(){ + return Seeker.stream().map(playerList::get).collect(Collectors.toList()); + } + + public static Player getFirstSeeker(){ + return playerList.get(Seeker.get(0)); + } + + public static List<Player> getSpectators(){ + return Spectator.stream().map(playerList::get).collect(Collectors.toList()); + } + + public static List<Player> getPlayers(){ + return new ArrayList<>(playerList.values()); + } + + public static Player getPlayer(String name) { + return playerList.get(name); + } + + public static void addHider(Player player) { + Hider.add(player.getName()); + Seeker.remove(player.getName()); + Spectator.remove(player.getName()); + playerList.put(player.getName(), player); + } + + public static void addSeeker(Player player) { + Hider.remove(player.getName()); + Seeker.add(player.getName()); + Spectator.remove(player.getName()); + playerList.put(player.getName(), player); + } + + public static void addSpectator(Player player) { + Hider.remove(player.getName()); + Seeker.remove(player.getName()); + Spectator.add(player.getName()); + playerList.put(player.getName(), player); + } + + public static void remove(Player player) { + Hider.remove(player.getName()); + Seeker.remove(player.getName()); + Spectator.remove(player.getName()); + playerList.remove(player.getName()); + } + + public static boolean onSameTeam(Player player1, Player player2) { + if(Hider.contains(player1.getName()) && Hider.contains(player2.getName())) return true; + else if(Seeker.contains(player1.getName()) && Seeker.contains(player2.getName())) return true; + else return Spectator.contains(player1.getName()) && Spectator.contains(player2.getName()); + } + + public static void reload() { + Hider.clear(); + Seeker.clear(); + Spectator.clear(); + } + + public static void createLobbyBoard(Player player) { + createLobbyBoard(player, true); + } + + private static void createLobbyBoard(Player player, boolean recreate) { + CustomBoard board = customBoards.get(player.getName()); + if(recreate) { + board = new CustomBoard(player, "&l&eHIDE AND SEEK"); + board.updateTeams(); + } + board.setLine("hiders", ChatColor.BOLD + "" + ChatColor.YELLOW + "HIDER %" + ChatColor.WHITE + getHiderPercent()); + board.setLine("seekers", ChatColor.BOLD + "" + ChatColor.RED + "SEEKER %" + ChatColor.WHITE + getSeekerPercent()); + board.addBlank(); + board.setLine("players", "Players: " + playerList.values().size()); + board.addBlank(); + if(lobbyCountdownEnabled){ + if(Game.countdownTime == -1){ + board.setLine("waiting", "Waiting for players..."); + } else { + board.setLine("waiting", "Starting in: "+ChatColor.GREEN + Game.countdownTime+"s"); + } + } else { + board.setLine("waiting", "Waiting for gamemaster..."); + } + board.display(); + customBoards.put(player.getName(), board); + } + + public static void createGameBoard(Player player){ + createGameBoard(player, true); + } + + private static void createGameBoard(Player player, boolean recreate){ + CustomBoard board = customBoards.get(player.getName()); + if(recreate) { + board = new CustomBoard(player, "&l&eHIDE AND SEEK"); + board.updateTeams(); + } + board.setLine("hiders", ChatColor.BOLD + "" + ChatColor.YELLOW + "HIDERS:" + ChatColor.WHITE + " " + Hider.size()); + board.setLine("seekers", ChatColor.BOLD + "" + ChatColor.RED + "SEEKERS:" + ChatColor.WHITE + " " + Seeker.size()); + board.addBlank(); + if(glowEnabled){ + if(Game.glow == null || Game.status == Status.STARTING || !Game.glow.isRunning()) + board.setLine("glow", "Glow: " + ChatColor.RED + "Inactive"); + else + board.setLine("glow", "Glow: " + ChatColor.GREEN + "Active"); + } + if(tauntEnabled && tauntCountdown){ + if(Game.taunt == null || Game.status == Status.STARTING) + board.setLine("taunt", "Taunt: " + ChatColor.YELLOW + "0m0s"); + else if(!tauntLast && Hider.size() == 1){ + board.setLine("taunt", "Taunt: " + ChatColor.YELLOW + "Expired"); + } else if(!Game.taunt.isRunning()) + board.setLine("taunt", "Taunt: " + ChatColor.YELLOW + Game.taunt.getDelay()/60 + "m" + Game.taunt.getDelay()%60 + "s"); + else + board.setLine("taunt", "Taunt: " + ChatColor.YELLOW + "Active"); + } + if(worldborderEnabled){ + if(Game.worldBorder == null || Game.status == Status.STARTING){ + board.setLine("board", "WorldBorder: " + ChatColor.YELLOW + "0m0s"); + } else if(!Game.worldBorder.isRunning()) { + board.setLine("board", "WorldBorder: " + ChatColor.YELLOW + Game.worldBorder.getDelay()/60 + "m" + Game.worldBorder.getDelay()%60 + "s"); + } else { + board.setLine("board", "WorldBorder: " + ChatColor.YELLOW + "Decreasing"); + } + } + if(glowEnabled || (tauntEnabled && tauntCountdown) || worldborderEnabled) + board.addBlank(); + board.setLine("time", "Time Left: " + ChatColor.GREEN + Game.timeLeft/60 + "m" + Game.timeLeft%60 + "s"); + board.addBlank(); + board.setLine("team", "Team: " + getTeam(player)); + board.display(); + customBoards.put(player.getName(), board); + } + + public static void removeBoard(Player player) { + ScoreboardManager manager = Bukkit.getScoreboardManager(); + assert manager != null; + player.setScoreboard(manager.getMainScoreboard()); + customBoards.remove(player.getName()); + } + + public static void reloadLobbyBoards() { + for(Player player : playerList.values()) + createLobbyBoard(player, false); + } + + public static void reloadGameBoards() { + for(Player player : playerList.values()) + createGameBoard(player, false); + } + + public static void reloadBoardTeams() { + for(CustomBoard board : customBoards.values()) + board.updateTeams(); + } + + private static String getSeekerPercent() { + if(playerList.values().size() < 2) + return " --"; + else + return " "+(int)(100*(1.0/playerList.size())); + } + + private static String getHiderPercent() { + if(playerList.size() < 2) + return " --"; + else + return " "+(int)(100-100*(1.0/playerList.size())); + } + + private static String getTeam(Player player) { + if(isHider(player)) return ChatColor.GOLD + "HIDER"; + else if(isSeeker(player)) return ChatColor.RED + "SEEKER"; + else if(isSpectator(player)) return ChatColor.GRAY + "SPECTATOR"; + else return ChatColor.WHITE + "UNKNOWN"; + } + +} + +class CustomBoard { + + private final Scoreboard board; + private final Objective obj; + private final Player player; + private final Map<String,Line> LINES; + private int blanks; + private boolean displayed; + + public CustomBoard(Player player, String title){ + ScoreboardManager manager = Bukkit.getScoreboardManager(); + assert manager != null; + this.board = manager.getNewScoreboard(); + this.LINES = new HashMap<>(); + this.player = player; + this.obj = board.registerNewObjective( + "Scoreboard", "dummy", ChatColor.translateAlternateColorCodes('&', title)); + this.blanks = 0; + this.displayed = false; + this.updateTeams(); + } + + public void updateTeams() { + try{ board.registerNewTeam("Hider"); } catch (Exception ignored){} + try{ board.registerNewTeam("Seeker"); } catch (Exception ignored){} + Team hiderTeam = board.getTeam("Hider"); + assert hiderTeam != null; + for(String entry : hiderTeam.getEntries()) + hiderTeam.removeEntry(entry); + for(Player player : Board.getHiders()) + hiderTeam.addEntry(player.getName()); + Team seekerTeam = board.getTeam("Seeker"); + assert seekerTeam != null; + for(String entry : seekerTeam.getEntries()) + seekerTeam.removeEntry(entry); + for(Player player : Board.getSeekers()) + seekerTeam.addEntry(player.getName()); + if(nametagsVisible) { + hiderTeam.setOption(Team.Option.NAME_TAG_VISIBILITY, Team.OptionStatus.FOR_OWN_TEAM); + seekerTeam.setOption(Team.Option.NAME_TAG_VISIBILITY, Team.OptionStatus.FOR_OTHER_TEAMS); + } else { + hiderTeam.setOption(Team.Option.NAME_TAG_VISIBILITY, Team.OptionStatus.NEVER); + seekerTeam.setOption(Team.Option.NAME_TAG_VISIBILITY, Team.OptionStatus.NEVER); + } + hiderTeam.setColor(ChatColor.GOLD); + seekerTeam.setColor(ChatColor.RED); + } + + public void setLine(String key, String message){ + Line line = LINES.get(key); + if(line == null) + addLine(key, message); + else + updateLine(key, message); + } + + private void addLine(String key, String message){ + Score score = obj.getScore(message); + score.setScore(LINES.values().size()+1); + Line line = new Line(LINES.values().size()+1, message); + LINES.put(key, line); + } + + public void addBlank(){ + if(displayed) return; + StringBuilder temp = new StringBuilder(); + for(int i = 0; i <= blanks; i ++) + temp.append(ChatColor.RESET); + blanks++; + addLine("blank"+blanks, temp.toString()); + } + + private void updateLine(String key, String message){ + Line line = LINES.get(key); + board.resetScores(line.getMessage()); + line.setMessage(message); + Score newScore = obj.getScore(message); + + newScore.setScore(line.getScore()); + } + + public void display() { + displayed = true; + obj.setDisplaySlot(DisplaySlot.SIDEBAR); + player.setScoreboard(board); + } + +} + +class Line { + + private final int score; + private String message; + + public Line(int score, String message){ + this.score = score; + this.message = message; + } + + public int getScore() { + return score; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + +}
\ No newline at end of file diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/CommandHandler.java b/src/main/java/net/tylermurphy/hideAndSeek/game/CommandHandler.java new file mode 100644 index 0000000..8df3cf2 --- /dev/null +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/CommandHandler.java @@ -0,0 +1,89 @@ +/* + * This file is part of Kenshins Hide and Seek + * + * Copyright (c) 2021 Tyler Murphy. + * + * Kenshins Hide and Seek free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * he Free Software Foundation version 3. + * + * Kenshins Hide and Seek is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +package net.tylermurphy.hideAndSeek.game; + +import static net.tylermurphy.hideAndSeek.configuration.Config.*; +import static net.tylermurphy.hideAndSeek.configuration.Localization.*; + +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import net.tylermurphy.hideAndSeek.command.*; + +public class CommandHandler { + + public static Map<String,ICommand> COMMAND_REGISTER = new LinkedHashMap<>(); + + private static void registerCommand(ICommand command) { + if(!COMMAND_REGISTER.containsKey(command.getLabel())) { + COMMAND_REGISTER.put(command.getLabel().toLowerCase(), command); + } + } + + public static void registerCommands() { + registerCommand(new About()); + registerCommand(new Help()); + registerCommand(new Setup()); + registerCommand(new Start()); + registerCommand(new Stop()); + registerCommand(new SetSpawnLocation()); + registerCommand(new SetLobbyLocation()); + registerCommand(new SetExitLocation()); + registerCommand(new SetBorder()); + registerCommand(new Reload()); + registerCommand(new SaveMap()); + registerCommand(new SetBounds()); + registerCommand(new Join()); + registerCommand(new Leave()); + registerCommand(new Top()); + registerCommand(new Wins()); + } + + public static boolean handleCommand(CommandSender sender, String[] args) { + if(!(sender instanceof Player)) { + sender.sendMessage(errorPrefix + message("COMMAND_PLAYER_ONLY")); + } else if(args.length < 1 || !COMMAND_REGISTER.containsKey(args[0].toLowerCase()) ) { + if(permissionsRequired && !sender.hasPermission("hideandseek.about")) { + sender.sendMessage(errorPrefix + LOCAL.get("")); + } else { + COMMAND_REGISTER.get("about").execute(sender, null); + } + } else { + if(!args[0].equalsIgnoreCase("about") && !args[0].equalsIgnoreCase("help") && SaveMap.runningBackup) { + sender.sendMessage(errorPrefix + message("MAPSAVE_INPROGRESS")); + } else if(permissionsRequired && !sender.hasPermission("hideandseek."+args[0].toLowerCase())) { + sender.sendMessage(errorPrefix + message("COMMAND_NOT_ALLOWED")); + } else { + try { + COMMAND_REGISTER.get(args[0].toLowerCase()).execute(sender,Arrays.copyOfRange(args, 1, args.length)); + } catch (Exception e) { + sender.sendMessage(errorPrefix + "An error has occured."); + e.printStackTrace(); + } + } + } + return true; + } + +} diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/EventListener.java b/src/main/java/net/tylermurphy/hideAndSeek/game/EventListener.java new file mode 100644 index 0000000..42589bc --- /dev/null +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/EventListener.java @@ -0,0 +1,264 @@ +/* + * This file is part of Kenshins Hide and Seek + * + * Copyright (c) 2021 Tyler Murphy. + * + * Kenshins Hide and Seek free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * he Free Software Foundation version 3. + * + * Kenshins Hide and Seek is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +package net.tylermurphy.hideAndSeek.game; + +import static net.tylermurphy.hideAndSeek.configuration.Config.*; + +import net.tylermurphy.hideAndSeek.Main; +import net.tylermurphy.hideAndSeek.util.Status; +import org.bukkit.*; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Snowball; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.*; +import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason; +import org.bukkit.event.player.*; + +import net.tylermurphy.hideAndSeek.util.Packet; +import org.bukkit.potion.PotionEffect; +import org.bukkit.projectiles.ProjectileSource; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import static net.tylermurphy.hideAndSeek.configuration.Localization.*; + +public class EventListener implements Listener { + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerJoin(PlayerJoinEvent event) { + Board.remove(event.getPlayer()); + Game.removeItems(event.getPlayer()); + if(Game.isNotSetup()) return; + if(autoJoin){ + Game.join(event.getPlayer()); + } else if(teleportToExit) { + if (event.getPlayer().getWorld().getName().equals("hideandseek_" + spawnWorld) || event.getPlayer().getWorld().getName().equals(lobbyWorld)) { + event.getPlayer().teleport(new Location(Bukkit.getWorld(exitWorld), exitPosition.getX(), exitPosition.getY(), exitPosition.getZ())); + event.getPlayer().setGameMode(GameMode.ADVENTURE); + } + } else { + if (event.getPlayer().getWorld().getName().equals("hideandseek_" + spawnWorld)) { + if(Game.status != Status.STANDBY){ + Game.join(event.getPlayer()); + } else { + event.getPlayer().teleport(new Location(Bukkit.getWorld(exitWorld), exitPosition.getX(), exitPosition.getY(), exitPosition.getZ())); + event.getPlayer().setGameMode(GameMode.ADVENTURE); + } + } + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onQuit(PlayerQuitEvent event) { + Board.remove(event.getPlayer()); + if(Game.status == Status.STANDBY) { + Board.reloadLobbyBoards(); + } else { + Board.reloadGameBoards(); + } + for(PotionEffect effect : event.getPlayer().getActivePotionEffects()){ + event.getPlayer().removePotionEffect(effect.getType()); + } + Game.removeItems(event.getPlayer()); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onKick(PlayerKickEvent event) { + Board.remove(event.getPlayer()); + if(Game.status == Status.STANDBY) { + Board.reloadLobbyBoards(); + } else { + Board.reloadGameBoards(); + } + for(PotionEffect effect : event.getPlayer().getActivePotionEffects()){ + event.getPlayer().removePotionEffect(effect.getType()); + } + Game.removeItems(event.getPlayer()); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onChat(AsyncPlayerChatEvent event){ + if(Board.isSeeker(event.getPlayer())){ + event.setCancelled(true); + Board.getSpectators().forEach(spectator -> spectator.sendMessage(ChatColor.GRAY + "[SPECTATOR] " + event.getPlayer().getName() + ": " + event.getMessage())); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onMove(PlayerMoveEvent event){ + if(!event.getPlayer().getWorld().getName().equals("hideandseek_" + spawnWorld)) return; + if(event.getPlayer().hasPermission("hideandseek.leavebounds")) return; + if(event.getTo() == null || event.getTo().getWorld() == null) return; + if(!event.getTo().getWorld().getName().equals("hideandseek_" + spawnWorld)) return; + if(event.getTo().getBlockX() < saveMinX || event.getTo().getBlockX() > saveMaxX || event.getTo().getBlockZ() < saveMinZ || event.getTo().getBlockZ() > saveMaxZ){ + event.setCancelled(true); + } + } + + public static final Map<UUID, Location> temp_loc = new HashMap<>(); + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerDeath(PlayerDeathEvent event){ + Player player = event.getEntity(); + if(!Board.isPlayer(player)) return; + event.setKeepInventory(true); + event.setDeathMessage(""); + temp_loc.put(player.getUniqueId(), player.getLocation()); + Main.plugin.getLogger().severe("Player "+player.getName() + " died when not supposed to. Attempting to roll back death."); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerRespawn(PlayerRespawnEvent event){ + Player player = event.getPlayer(); + if(!Board.isPlayer(player)) return; + if(temp_loc.containsKey(player.getUniqueId())){ + player.teleport(temp_loc.get(player.getUniqueId())); + temp_loc.remove(player.getUniqueId()); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onEntityDamage(EntityDamageEvent event) { + try { + if (event.getEntity() instanceof Player) { + Player player = (Player) event.getEntity(); + if (!Board.isPlayer(player)) { + if (event instanceof EntityDamageByEntityEvent) { + Entity damager = ((EntityDamageByEntityEvent) event).getDamager(); + if (damager instanceof Player) { + if(Board.isPlayer(damager)){ + event.setCancelled(true); + return; + } + } + } + } + if (Game.status != Status.PLAYING) { + event.setCancelled(true); + return; + } + Player attacker = null; + if (event instanceof EntityDamageByEntityEvent) { + Entity damager = ((EntityDamageByEntityEvent) event).getDamager(); + if (damager instanceof Player) { + attacker = (Player) damager; + if (Board.onSameTeam(player, attacker)) event.setCancelled(true); + if (Board.isSpectator(player)) event.setCancelled(true); + } else if(damager instanceof Arrow){ + ProjectileSource source = ((Arrow) damager).getShooter(); + if(source instanceof Player){ + attacker = (Player) source; + if (Board.onSameTeam(player, attacker)) event.setCancelled(true); + if (Board.isSpectator(player)) event.setCancelled(true); + } + } + } + if (player.getHealth() - event.getDamage() < 0 || !pvpEnabled) { + if (spawnPosition == null) return; + event.setCancelled(true); + AttributeInstance attribute = player.getAttribute(Attribute.GENERIC_MAX_HEALTH); + if(attribute != null) + player.setHealth(attribute.getValue()); + player.teleport(new Location(Bukkit.getWorld("hideandseek_" + spawnWorld), spawnPosition.getX(), spawnPosition.getY(), spawnPosition.getZ())); + Packet.playSound(player, Sound.ENTITY_PLAYER_DEATH, 1, 1); + if (Board.isSeeker(player)) { + Bukkit.broadcastMessage(message("GAME_PLAYER_DEATH").addPlayer(player).toString()); + } + if (Board.isHider(player)) { + if (attacker == null) { + Game.broadcastMessage(message("GAME_PLAYER_FOUND").addPlayer(player).toString()); + } else { + Game.broadcastMessage(message("GAME_PLAYER_FOUND_BY").addPlayer(player).addPlayer(attacker).toString()); + } + Board.addSeeker(player); + } + Game.resetPlayer(player); + Board.reloadBoardTeams(); + } + } + } catch (Exception e){ + Main.plugin.getLogger().severe("Entity Damage Event Error: " + e.getMessage()); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onProjectile(ProjectileLaunchEvent event) { + if(Game.status != Status.PLAYING) return; + if(event.getEntity() instanceof Snowball) { + if(!glowEnabled) return; + Snowball snowball = (Snowball) event.getEntity(); + if(snowball.getShooter() instanceof Player) { + Player player = (Player) snowball.getShooter(); + if(Board.isHider(player)) { + Game.glow.onProjectile(); + snowball.remove(); + player.getInventory().remove(Material.SNOWBALL); + } + } + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onFoodLevelChange(FoodLevelChangeEvent event) { + if(event.getEntity() instanceof Player) { + if(!Board.isPlayer((Player) event.getEntity())) return; + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerRegainHealth(EntityRegainHealthEvent event) { + if(event.getRegainReason() == RegainReason.SATIATED || event.getRegainReason() == RegainReason.REGEN) { + if(event.getEntity() instanceof Player) { + if(!Board.isPlayer((Player) event.getEntity())) return; + event.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerCommand(PlayerCommandPreprocessEvent event) { + Player player = event.getPlayer(); + String message = event.getMessage(); + String[] array = message.split(" "); + if(array[0].equalsIgnoreCase("/kill")){ + if(Board.isPlayer(player)){ + Main.plugin.getLogger().info("Blocking "+player.getName()+ "from running /kill with anyone associated in the lobby"); + event.setCancelled(true); + } else if(array.length > 1){ + for(int i=1; i<array.length; i++){ + if(Board.isPlayer(array[i])){ + Main.plugin.getLogger().info("Blocking "+player.getName()+ "from running /kill with anyone associated in the lobby"); + event.setCancelled(true); + return; + } + } + } + } + } +}
\ No newline at end of file diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/Game.java b/src/main/java/net/tylermurphy/hideAndSeek/game/Game.java new file mode 100644 index 0000000..225eab0 --- /dev/null +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/Game.java @@ -0,0 +1,543 @@ +/* + * This file is part of Kenshins Hide and Seek + * + * Copyright (c) 2020-2021. Tyler Murphy + * + * Kenshins Hide and Seek free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * he Free Software Foundation version 3. + * + * Kenshins Hide and Seek is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +package net.tylermurphy.hideAndSeek.game; + +import static net.tylermurphy.hideAndSeek.configuration.Config.*; + +import net.md_5.bungee.api.ChatColor; +import net.tylermurphy.hideAndSeek.configuration.Items; +import net.tylermurphy.hideAndSeek.database.Database; +import net.tylermurphy.hideAndSeek.util.Status; +import net.tylermurphy.hideAndSeek.util.WinType; +import net.tylermurphy.hideAndSeek.world.WorldLoader; +import org.bukkit.*; +import org.bukkit.attribute.Attribute; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Firework; +import org.bukkit.entity.Player; + +import net.tylermurphy.hideAndSeek.Main; +import net.tylermurphy.hideAndSeek.util.Packet; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.FireworkMeta; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.beans.EventHandler; +import java.io.File; +import java.util.*; +import java.util.stream.Collectors; + +import static net.tylermurphy.hideAndSeek.configuration.Localization.*; +import static net.tylermurphy.hideAndSeek.game.Game.broadcastMessage; + +public class Game { + + public static Taunt taunt; + public static Glow glow; + public static Border worldBorder; + public static WorldLoader worldLoader; + public static int tick = 0; + public static int countdownTime = -1; + public static int gameId = 0; + public static int timeLeft = 0; + public static Status status = Status.STANDBY; + + static { + worldLoader = new WorldLoader(spawnWorld); + } + + public static void start(Player seeker){ + if(status == Status.STARTING || status == Status.PLAYING) return; + if(worldLoader.getWorld() != null) { + worldLoader.rollback(); + } else { + worldLoader.loadMap(); + } + Board.reload(); + for(Player temp : Board.getPlayers()) { + if(temp.getName().equals(seeker.getName())) + continue; + Board.addHider(temp); + } + Board.addSeeker(seeker); + currentWorldborderSize = worldborderSize; + for(Player player : Board.getPlayers()) { + player.getInventory().clear(); + player.setGameMode(GameMode.ADVENTURE); + player.teleport(new Location(Bukkit.getWorld("hideandseek_"+spawnWorld), spawnPosition.getX(),spawnPosition.getY(),spawnPosition.getZ())); + for(PotionEffect effect : player.getActivePotionEffects()){ + player.removePotionEffect(effect.getType()); + } + } + for(Player player : Board.getSeekers()) { + player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS,1000000,127,false,false)); + player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW,1000000,127,false,false)); + player.sendTitle(ChatColor.RED + "" + ChatColor.BOLD + "SEEKER", ChatColor.WHITE + message("SEEKERS_SUBTITLE").toString(), 10, 70, 20); + } + for(Player player : Board.getHiders()) { + player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED,1000000,5,false,false)); + player.sendTitle(ChatColor.GOLD + "" + ChatColor.BOLD + "HIDER", ChatColor.WHITE + message("HIDERS_SUBTITLE").toString(), 10, 70, 20); + } + if(tauntEnabled) + taunt = new Taunt(); + if (glowEnabled) + glow = new Glow(); + worldBorder = new Border(); + worldBorder.resetWorldborder("hideandseek_"+spawnWorld); + if(gameLength > 0) + timeLeft = gameLength; + for(Player player : Board.getPlayers()) + Board.createGameBoard(player); + Board.reloadGameBoards(); + status = Status.STARTING; + int temp = gameId; + broadcastMessage(messagePrefix + message("START_COUNTDOWN").addAmount(30)); + sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(20), gameId, 20 * 10); + sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(10), gameId, 20 * 20); + sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(5), gameId, 20 * 25); + sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(3), gameId, 20 * 27); + sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(2), gameId, 20 * 28); + sendDelayedMessage(messagePrefix + message("START_COUNTDOWN").addAmount(1), gameId, 20 * 29); + Bukkit.getServer().getScheduler().runTaskLater(Main.plugin, () -> { + if(temp != gameId) return; + broadcastMessage(messagePrefix + message("START")); + for(Player player : Board.getPlayers()) resetPlayer(player); + status = Status.PLAYING; + }, 20 * 30); + } + + public static void stop(WinType type){ + if(status == Status.STANDBY) return; + tick = 0; + countdownTime = -1; + status = Status.STANDBY; + gameId++; + timeLeft = 0; + List<UUID> players = Board.getPlayers().stream().map(Entity::getUniqueId).collect(Collectors.toList()); + if(type == WinType.HIDER_WIN){ + List<UUID> winners = Board.getHiders().stream().map(Entity::getUniqueId).collect(Collectors.toList()); + Database.playerInfo.addWins(players, winners, type); + } else if(type == WinType.SEEKER_WIN){ + List<UUID> winners = new ArrayList<>(); + winners.add(Board.getFirstSeeker().getUniqueId()); + Database.playerInfo.addWins(players, winners, type); + } + worldBorder.resetWorldborder("hideandseek_"+spawnWorld); + for(Player player : Board.getPlayers()) { + Board.createLobbyBoard(player); + player.setGameMode(GameMode.ADVENTURE); + Board.addHider(player); + player.getInventory().clear(); + player.teleport(new Location(Bukkit.getWorld(lobbyWorld), lobbyPosition.getX(),lobbyPosition.getY(),lobbyPosition.getZ())); + for(PotionEffect effect : player.getActivePotionEffects()){ + player.removePotionEffect(effect.getType()); + } + player.addPotionEffect(new PotionEffect(PotionEffectType.HEAL, 1, 100)); + for(Player temp : Board.getPlayers()) { + Packet.setGlow(player, temp, false); + } + } + EventListener.temp_loc.clear(); + worldLoader.unloadMap(); + Board.reloadLobbyBoards(); + } + + public static boolean isNotSetup() { + if(spawnPosition.getBlockX() == 0 && spawnPosition.getBlockY() == 0 && spawnPosition.getBlockZ() == 0) return true; + if(lobbyPosition.getBlockX() == 0 && lobbyPosition.getBlockY() == 0 && lobbyPosition.getBlockZ() == 0) return true; + if(exitPosition.getBlockX() == 0 && exitPosition.getBlockY() == 0 && exitPosition.getBlockZ() == 0) return true; + File destenation = new File(Main.root+File.separator+"hideandseek_"+spawnWorld); + if(!destenation.exists()) return true; + return saveMinX == 0 || saveMinZ == 0 || saveMaxX == 0 || saveMaxZ == 0; + } + + public static void onTick() { + if(isNotSetup()) return; + if(status == Status.STANDBY) whileWaiting(); + else if(status == Status.STARTING) whileStarting(); + else if(status == Status.PLAYING) whilePlaying(); + tick++; + } + + public static void resetWorldborder(String worldName){ + worldBorder.resetWorldborder(worldName); + } + + public static void broadcastMessage(String message) { + for(Player player : Board.getPlayers()) { + player.sendMessage(message); + } + } + + public static void resetPlayer(Player player) { + player.getInventory().clear(); + for (PotionEffect effect : player.getActivePotionEffects()) { + player.removePotionEffect(effect.getType()); + } + if (Board.isSeeker(player)) { + if(pvpEnabled) + for(ItemStack item : Items.SEEKER_ITEMS) + player.getInventory().addItem(item); + for(PotionEffect effect : Items.SEEKER_EFFECTS) + player.addPotionEffect(effect); + } else if (Board.isHider(player)) { + if(pvpEnabled) + for(ItemStack item : Items.HIDER_ITEMS) + player.getInventory().addItem(item); + for(PotionEffect effect : Items.HIDER_EFFECTS) + player.addPotionEffect(effect); + if(glowEnabled) { + ItemStack snowball = new ItemStack(Material.SNOWBALL, 1); + ItemMeta snowballMeta = snowball.getItemMeta(); + assert snowballMeta != null; + snowballMeta.setDisplayName("Glow Powerup"); + List<String> snowballLore = new ArrayList<>(); + snowballLore.add("Throw to make all seekers glow"); + snowballLore.add("Last 30s, all hiders can see it"); + snowballLore.add("Time stacks on multi use"); + snowballMeta.setLore(snowballLore); + snowball.setItemMeta(snowballMeta); + player.getInventory().addItem(snowball); + } + } + } + + public static void join(Player player){ + if(Game.status == Status.STANDBY) { + player.getInventory().clear(); + Board.addHider(player); + if(announceMessagesToNonPlayers) Bukkit.broadcastMessage(messagePrefix + message("GAME_JOIN").addPlayer(player)); + else Game.broadcastMessage(messagePrefix + message("GAME_JOIN").addPlayer(player)); + player.teleport(new Location(Bukkit.getWorld(lobbyWorld), lobbyPosition.getX(),lobbyPosition.getY(),lobbyPosition.getZ())); + player.setGameMode(GameMode.ADVENTURE); + Board.createLobbyBoard(player); + Board.reloadLobbyBoards(); + } else { + Board.addSpectator(player); + player.sendMessage(messagePrefix + message("GAME_JOIN_SPECTATOR")); + player.setGameMode(GameMode.SPECTATOR); + Board.createGameBoard(player); + player.teleport(new Location(Bukkit.getWorld("hideandseek_"+spawnWorld), spawnPosition.getX(),spawnPosition.getY(),spawnPosition.getZ())); + player.sendTitle(ChatColor.GRAY + "" + ChatColor.BOLD + "SPECTATING", ChatColor.WHITE + message("SPECTATOR_SUBTITLE").toString(), 10, 70, 20); + } + + player.setFoodLevel(20); + player.setHealth(Objects.requireNonNull(player.getAttribute(Attribute.GENERIC_MAX_HEALTH)).getBaseValue()); + } + + public static void removeItems(Player player){ + for(ItemStack si : Items.SEEKER_ITEMS) + for(ItemStack i : player.getInventory().getContents()) + if(si.isSimilar(i)) player.getInventory().remove(i); + for(ItemStack hi : Items.HIDER_ITEMS) + for(ItemStack i : player.getInventory().getContents()) + if(hi.isSimilar(i)) player.getInventory().remove(i); + } + + private static void whileWaiting() { + if(lobbyCountdownEnabled){ + if(lobbyMin <= Board.size()){ + if(countdownTime == -1) + countdownTime = countdown; + if(Board.size() >= changeCountdown) + countdownTime = Math.min(countdownTime, 10); + if(tick % 20 == 0) + countdownTime--; + if(countdownTime == 0){ + Optional<Player> rand = Board.getPlayers().stream().skip(new Random().nextInt(Board.size())).findFirst(); + if(!rand.isPresent()){ + Main.plugin.getLogger().warning("Failed to select random seeker."); + return; + } + String seekerName = rand.get().getName(); + Player seeker = Board.getPlayer(seekerName); + start(seeker); + } + } else { + countdownTime = -1; + } + } + } + + private static void whileStarting(){ + checkWinConditions(); + } + + private static void whilePlaying() { + for(Player hider : Board.getHiders()) { + int distance = 100, temp = 100; + for(Player seeker : Board.getSeekers()) { + try { + temp = (int) hider.getLocation().distance(seeker.getLocation()); + } catch (Exception e){ + //Players in different worlds, NOT OK!!! + } + if(distance > temp) { + distance = temp; + } + } + switch(tick%10) { + case 0: + if(distance < 30) Packet.playSound(hider, Sound.BLOCK_NOTE_BLOCK_BASEDRUM, .5f, 1f); + if(distance < 10) Packet.playSound(hider, Sound.BLOCK_NOTE_BLOCK_BIT, .3f, 1f); + break; + case 3: + if(distance < 30) Packet.playSound(hider, Sound.BLOCK_NOTE_BLOCK_BASEDRUM, .3f, 1f); + if(distance < 10) Packet.playSound(hider, Sound.BLOCK_NOTE_BLOCK_BIT, .3f, 1f); + break; + case 6: + if(distance < 10) Packet.playSound(hider, Sound.BLOCK_NOTE_BLOCK_BIT, .3f, 1f); + break; + case 9: + if(distance < 20) Packet.playSound(hider, Sound.BLOCK_NOTE_BLOCK_BIT, .3f, 1f); + break; + } + } + if(tick%20 == 0) { + if(gameLength > 0) { + Board.reloadGameBoards(); + timeLeft--; + } + if(worldborderEnabled) worldBorder.update(); + if(tauntEnabled) taunt.update(); + if (glowEnabled) glow.update(); + } + checkWinConditions(); + } + + private static void checkWinConditions(){ + if(Board.sizeHider() < 1) { + if(announceMessagesToNonPlayers) Bukkit.broadcastMessage(gameoverPrefix + message("GAME_GAMEOVER_HIDERS_FOUND")); + else broadcastMessage(gameoverPrefix + message("GAME_GAMEOVER_HIDERS_FOUND")); + stop(WinType.SEEKER_WIN); + } else if(Board.sizeSeeker() < 1) { + if(announceMessagesToNonPlayers) Bukkit.broadcastMessage(abortPrefix + message("GAME_GAMEOVER_SEEKERS_QUIT")); + else broadcastMessage(abortPrefix + message("GAME_GAMEOVER_SEEKERS_QUIT")); + stop(WinType.NONE); + } else if(timeLeft < 1) { + if(announceMessagesToNonPlayers) Bukkit.broadcastMessage(gameoverPrefix + message("GAME_GAMEOVER_TIME")); + else broadcastMessage(gameoverPrefix + message("GAME_GAMEOVER_TIME")); + stop(WinType.HIDER_WIN); + } + } + + private static void sendDelayedMessage(String message, int gameId, int delay) { + Bukkit.getScheduler().runTaskLaterAsynchronously(Main.plugin, () -> { + if(gameId == Game.gameId) + broadcastMessage(message); + }, delay); + } + +} + +class Glow { + + private int glowTime; + private boolean running; + + public Glow() { + this.glowTime = 0; + } + + public void onProjectile() { + if(glowStackable) glowTime += glowLength; + else glowTime = glowLength; + if(!running) + startGlow(); + } + + private void startGlow() { + running = true; + for(Player hider : Board.getHiders()) { + for(Player seeker : Board.getSeekers()) { + Packet.setGlow(hider, seeker, true); + } + } + } + + protected void update() { + if(running) { + glowTime--; + glowTime = Math.max(glowTime, 0); + if (glowTime == 0) { + stopGlow(); + } + } + } + + private void stopGlow() { + running = false; + for(Player hider : Board.getHiders()) { + for (Player seeker : Board.getSeekers()) { + Packet.setGlow(hider, seeker, false); + } + } + } + + public boolean isRunning() { + return running; + } + +} + +class Taunt { + + private String tauntPlayer; + private int delay; + private boolean running; + + public Taunt() { + this.delay = tauntDelay; + } + + protected void update() { + if(delay == 0) { + if(running) launchTaunt(); + else if(tauntLast || Board.sizeHider() > 1) executeTaunt(); + } else { + delay--; + delay = Math.max(delay, 0); + } + } + + private void executeTaunt() { + Optional<Player> rand = Board.getHiders().stream().skip(new Random().nextInt(Board.size())).findFirst(); + if(!rand.isPresent()){ + Main.plugin.getLogger().warning("Failed to select random seeker."); + return; + } + Player taunted = rand.get(); + taunted.sendMessage(message("TAUNTED").toString()); + broadcastMessage(tauntPrefix + message("TAUNT")); + tauntPlayer = taunted.getName(); + running = true; + delay = 30; + } + + private void launchTaunt(){ + Player taunted = Board.getPlayer(tauntPlayer); + if(taunted != null) { + if(!Board.isHider(taunted)){ + Main.plugin.getLogger().info("Taunted played died and is now seeker. Skipping taunt."); + tauntPlayer = ""; + running = false; + delay = tauntDelay; + return; + } + World world = taunted.getLocation().getWorld(); + if(world == null){ + Main.plugin.getLogger().severe("Game world is null while trying to launch taunt."); + tauntPlayer = ""; + running = false; + delay = tauntDelay; + return; + } + Firework fw = (Firework) world.spawnEntity(taunted.getLocation(), EntityType.FIREWORK); + FireworkMeta fwm = fw.getFireworkMeta(); + fwm.setPower(4); + fwm.addEffect(FireworkEffect.builder() + .withColor(Color.BLUE) + .withColor(Color.RED) + .withColor(Color.YELLOW) + .with(FireworkEffect.Type.STAR) + .with(FireworkEffect.Type.BALL) + .with(FireworkEffect.Type.BALL_LARGE) + .flicker(true) + .withTrail() + .build()); + fw.setFireworkMeta(fwm); + broadcastMessage(tauntPrefix + message("TAUNT_ACTIVATE")); + } + tauntPlayer = ""; + running = false; + delay = tauntDelay; + } + + public int getDelay(){ + return delay; + } + + public boolean isRunning() { + return running; + } + +} + +class Border { + + private int delay; + private boolean running; + + public Border() { + delay = 60 * worldborderDelay; + } + + void update(){ + if(delay == 30 && !running){ + broadcastMessage(worldborderPrefix + message("WORLDBORDER_WARN")); + } else if(delay == 0){ + if(running){ + delay = 60 * worldborderDelay; + running = false; + } + else decreaceWorldborder(); + } + delay--; + } + + private void decreaceWorldborder() { + if(currentWorldborderSize-100 > 100) { + running = true; + broadcastMessage(worldborderPrefix + message("WORLDBORDER_DECREASING")); + currentWorldborderSize -= 100; + World world = Bukkit.getWorld("hideandseek_"+spawnWorld); + assert world != null; + org.bukkit.WorldBorder border = world.getWorldBorder(); + border.setSize(border.getSize()-100,30); + delay = 30; + } + } + + public void resetWorldborder(String worldName) { + World world = Bukkit.getWorld(worldName); + assert world != null; + org.bukkit.WorldBorder border = world.getWorldBorder(); + if(worldborderEnabled) { + border.setSize(worldborderSize); + border.setCenter(worldborderPosition.getX(), worldborderPosition.getZ()); + currentWorldborderSize = worldborderSize; + } else { + border.setSize(30000000); + border.setCenter(0, 0); + } + } + + public int getDelay(){ + return delay; + } + + public boolean isRunning() { + return running; + } + +}
\ No newline at end of file |