package pro.marvin.minecraft.mcmurder; import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.Sign; import org.bukkit.entity.Entity; import org.bukkit.entity.Item; import org.bukkit.entity.Player; import org.bukkit.entity.Snowball; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.SignChangeEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerPickupItemEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.Vector; import java.util.*; public class Murder extends JavaPlugin implements Listener { // Game-stats ... public HashMap<Integer, Boolean> arenaConfig = new HashMap<>(); private HashMap<Integer, Block> updateSigns = new HashMap<>(); private HashMap<Integer, Boolean> gameStarted = new HashMap<>(); private HashMap<Integer, Integer> countdown = new HashMap<>(); public List<Player> playersList = new ArrayList<>(); public HashMap<String, Integer> playersMap = new HashMap<>(); public HashMap<String, String> playersTeam = new HashMap<>(); public HashMap<String, Boolean> playersAlive = new HashMap<>(); private HashMap<String, Long> reloadTime = new HashMap<>(); // Config-file public static int maxPlayers = 8; public static String gameWorldPrefix; /** * Set-up important timers and other stuff */ @Override public void onEnable() { getCommand("mcm").setExecutor(new CommandManager(this)); getServer().getPluginManager().registerEvents(this, this); init(); loadConfig(); // Start repeating tasks countdown(); reloadTime(); updateSigns(); } /** * Remove every player from the arena */ @Override public void onDisable() { for (Player p : playersList) { p.setGameMode(GameMode.ADVENTURE); p.getInventory().clear(); p.teleport(mcmSpawn()); p.removePotionEffect(PotionEffectType.BLINDNESS); p.removePotionEffect(PotionEffectType.SLOW); p.setExp(0); p.setLevel(0); List<Entity> entList = p.getWorld().getEntities(); for (Entity current : entList) { if (current instanceof Item) { current.remove(); } } } // Show everyone to everyone for (Player playersInMap : playersList) { for (Player playersInMap2 : playersList) { playersInMap.showPlayer(playersInMap2); playersInMap2.showPlayer(playersInMap); } } } /** * Prepare the HashMaps */ private void init() { for (int i = 1; i < 100; i++) { gameStarted.put(i, false); countdown.put(i, -1); arenaConfig.put(i, false); } } /** * A game will start. Prepare the players and send them in the arena. * * @param mapId Which map / arena will start */ public void startGame(int mapId) { countdown.put(mapId, -1); // Prepare world World w = getServer().getWorld(gameWorldPrefix + mapId); w.setTime(6000); w.setDifficulty(Difficulty.PEACEFUL); w.setStorm(false); // Show everyone to everyone for (Player playersInMap : getPlayerInArena(mapId)) { for (Player playersInMap2 : getPlayerInArena(mapId)) { playersInMap.showPlayer(playersInMap2); playersInMap2.showPlayer(playersInMap); } } // Prepare players for (Player p : getPlayerInArena(mapId)) { preparePlayer(p); } chooseMurdererAndBystanderWithWeapon(mapId); // Show player's team for (Player p : getPlayerInArena(mapId)) { if (playerIsMurderer(p)) { p.sendMessage(Texts.PRE_TEXT + Texts.GAME_MURDERER); } else if (playerIsBystanderWithWeapon(p)) { p.sendMessage(Texts.PRE_TEXT + Texts.GAME_BYSTANDER_WEAPON); } else if (playerIsBystander(p)) { p.sendMessage(Texts.PRE_TEXT + Texts.GAME_BYSTANDER); } p.playSound(p.getLocation(), Sound.ENTITY_ENDERDRAGON_GROWL, 1, 1); } // Start! gameStarted.put(mapId, true); } /** * A game will stop. Remove weapons and start a firework. * * @param mapId Which map / arena will stop */ public void stopGame(final int mapId, boolean restart) { if (!getGameStarted(mapId)) return; // Get the murderer Player murderer = getPlayerInArena(mapId).get(0); // Dummy for (Player players : getPlayerInArena(mapId)) { if (playerIsMurderer(players)) murderer = players; } // Send a message with the score for (Player p : getPlayerInArena(mapId)) { reloadTime.put(p.getName(), System.currentTimeMillis() - 5000); playersAlive.remove(p.getName()); p.getInventory().clear(); p.removePotionEffect(PotionEffectType.SLOW); p.sendMessage(Texts.PRE_TEXT + Texts.GAME_ENDED.replace("%murderer", murderer.getDisplayName())); } // Remove Players' Team for (Player p : getPlayerInArena(mapId)) { playersTeam.remove(p.getName()); } // Remove every item on the ground World world = getServer().getWorld(gameWorldPrefix + mapId); List<Entity> entList = world.getEntities(); for (Entity current : entList) { if (current instanceof Item) { current.remove(); } } gameStarted.put(mapId, false); if (restart) { countdown.put(mapId, 30); } else { for (Player p : getPlayerInArena(mapId)) { p.teleport(mcmSpawn()); p.setAllowFlight(false); playersList.remove(p); playersMap.remove(p.getName()); playersTeam.remove(p.getName()); playersAlive.remove(p.getName()); reloadTime.remove(p.getName()); p.getInventory().clear(); p.setExp(0); p.setLevel(0); } } } private void chooseMurdererAndBystanderWithWeapon(int mapId) { Object[] players = getPlayerInArena(mapId).toArray(); Random r = new Random(); int randomMurderer = r.nextInt(players.length); int randomWeapon = r.nextInt(players.length); if (randomMurderer != randomWeapon) { playersTeam.put(((Player) players[randomMurderer]).getName(), "murderer"); playersTeam.put(((Player) players[randomWeapon]).getName(), "bystanderWeapon"); for (int i = 0; i < players.length; i++) { if (i != randomMurderer && i != randomWeapon) { playersTeam.put(((Player) players[i]).getName(), "bystander"); } } } else { chooseMurdererAndBystanderWithWeapon(mapId); } } /** * A player joined the arena. Start the countdown (if possible) and put him/her in a team * * @param p Player which joined * @param mapId Which map / arena he/she joined */ public void playerJoinedArena(final Player p, final int mapId) { if (playersList.contains(p)) { // Player is already in game p.sendMessage(Texts.PRE_TEXT + Texts.GAME_ALREADY_INGAME); return; } if (getPlayerInArena(mapId).size() > maxPlayers - 1) { // Arena full p.sendMessage(Texts.PRE_TEXT + Texts.GAME_ARENA_FULL); return; } // Prepare player playersList.add(p); playersMap.put(p.getName(), mapId); reloadTime.put(p.getName(), System.currentTimeMillis() - 5000); p.getInventory().clear(); p.setAllowFlight(false); p.setGameMode(GameMode.ADVENTURE); p.teleport(randomSpawn(mapId)); // Announce the new player for (Player player : getPlayerInArena(mapId)) { player.sendMessage(Texts.PRE_TEXT + p.getDisplayName() + Texts.GAME_PLAYER_JOINED); } // Not enough players to start the countdown if (getPlayerInArena(mapId).size() < 2) { p.sendMessage(Texts.PRE_TEXT + Texts.GAME_NOT_ENOUGH_PLAYERS); return; } if (countdown.get(mapId) != -1) { return; } countdown.put(mapId, 30); } /** * Load data from the config-file */ public void loadConfig() { saveDefaultConfig(); reloadConfig(); gameWorldPrefix = getConfig().getString("gameWorldPrefix"); updateSigns.clear(); arenaConfig.clear(); for (int i = 1; i < 100; i++) { List<Double> sign = getConfig().getDoubleList("maps." + i + ".sign"); if (!sign.isEmpty()) { World w = Bukkit.getWorld(getConfig().getString("maps." + i + ".signWorld")); updateSigns.put(i, w.getBlockAt(new Location(w, sign.get(0), sign.get(1), sign.get(2)))); } arenaConfig.put(i, getConfig().getBoolean("maps." + i + ".enabled")); } } /** * A player died or the game started: He/She needs stuff and a teleport * * @param p Player which will be prepared */ private void preparePlayer(final Player p) { getServer().getScheduler().scheduleSyncDelayedTask(this, () -> { p.setAllowFlight(false); p.setGameMode(GameMode.ADVENTURE); p.setAllowFlight(false); p.setHealth(20); p.setFoodLevel(20); p.setLevel(0); p.teleport(randomSpawn(getPlayersArena(p))); p.getInventory().clear(); playersAlive.put(p.getName(), true); reloadTime.put(p.getName(), System.currentTimeMillis() - 5000); if (!getGameStarted(getPlayersArena(p))) { return; } if (playerIsMurderer(p)) { p.getInventory().setHeldItemSlot(1); List<String> lsKnife = new ArrayList<>(); lsKnife.add(Texts.GAME_HOWTO_KNIFE); p.getInventory().addItem(setName(new ItemStack(Material.STONE_AXE, 1), "§2Knife", lsKnife, 1)); } else if (playerIsBystanderWithWeapon(p)) { p.getInventory().setHeldItemSlot(1); List<String> lsWeapon = new ArrayList<>(); lsWeapon.add(Texts.GAME_HOWTO_WEAPON); lsWeapon.add(Texts.GAME_RELOAD_WEAPON + "5s"); p.getInventory().addItem(setName(new ItemStack(Material.WOOD_HOE, 1), "§2Gun", lsWeapon, 1)); } else { p.getInventory().setHeldItemSlot(0); } }); } /** * Remove player from arena and teleport him/her back to the lobby * * @param p Which player will be removed */ public void playerLeave(Player p) { int oldArena = getPlayersArena(p); if (oldArena == 0) return; playersList.remove(p); // Announce event for (Player player : getPlayerInArena(getPlayersArena(p))) { player.sendMessage(Texts.PRE_TEXT + p.getDisplayName() + Texts.GAME_PLAYER_LEFT); player.showPlayer(p); } for (PotionEffect effect : p.getActivePotionEffects()) { p.removePotionEffect(effect.getType()); } // Does the game need to end? if (getPlayerInArena(oldArena).size() < 2 && getGameStarted(oldArena)) { for (Player player : getPlayerInArena(oldArena)) { player.sendMessage(Texts.PRE_TEXT + Texts.GAME_STOPPED); } stopGame(oldArena, true); return; } // Does the game need to end? if (getPlayerInArena(oldArena).size() >= 2 && getGameStarted(oldArena)) { if (playerIsMurderer(p)) { stopGame(oldArena, true); } else if (p.getInventory().contains(Material.WOOD_HOE)) { List<String> lsWeapon = new ArrayList<>(); lsWeapon.add(Texts.GAME_HOWTO_WEAPON); lsWeapon.add(Texts.GAME_RELOAD_WEAPON + "5s"); p.getWorld().dropItemNaturally(p.getLocation(), setName(new ItemStack(Material.WOOD_HOE, 1), "§2Gun", lsWeapon, 1)); p.setItemInHand(new ItemStack(Material.AIR)); reloadTime.put(p.getName(), System.currentTimeMillis()); } } // Teleport player back and remove his/her stuff p.teleport(mcmSpawn()); p.setAllowFlight(false); playersMap.remove(p.getName()); playersTeam.remove(p.getName()); playersAlive.remove(p.getName()); reloadTime.remove(p.getName()); p.getInventory().clear(); p.setExp(0); p.setLevel(0); } @EventHandler public void onInteract(PlayerInteractEvent e) { // It's the knife! Throw it! if (getPlayerInGame(e.getPlayer()) && e.getPlayer().getItemInHand().getType() == Material.STONE_AXE && playerIsMurderer(e.getPlayer()) && getGameStarted(getPlayersArena(e.getPlayer()))) { if (e.getAction() == Action.RIGHT_CLICK_AIR || (e.getAction() == Action.RIGHT_CLICK_BLOCK && e.getClickedBlock().getType() != Material.WOOD_BUTTON)) { if (e.getPlayer().getItemInHand().hasItemMeta() && e.getPlayer().getItemInHand().getItemMeta().getDisplayName().equals("§2Knife")) { final Player p = e.getPlayer(); ItemStack playersAxe = e.getPlayer().getItemInHand(); Location l = p.getEyeLocation().subtract(0, 0.4, 0); final Item i = p.getWorld().dropItem(l, playersAxe); i.setVelocity(p.getLocation().getDirection().multiply(1.2)); p.setItemInHand(new ItemStack(Material.AIR)); BukkitRunnable runnable = new BukkitRunnable() { @Override public void run() { if (i.isOnGround()) { i.getWorld().playSound(i.getLocation(), Sound.BLOCK_ANVIL_LAND, (float) 0.1, (float) -5); cancel(); return; } if (!i.getNearbyEntities(1.5D, 1.5D, 1.5D).isEmpty()) { for (Player victim : getPlayerInArena(getPlayersArena(p))) { if (victim.getLocation().distance(i.getLocation()) <= 1.5D && !playerIsMurderer(victim) && playerIsAlive(victim) && getGameStarted(getPlayersArena(victim))) { if (victim.getInventory().contains(Material.WOOD_HOE)) { List<String> lsWeapon = new ArrayList<>(); lsWeapon.add(Texts.GAME_HOWTO_WEAPON); lsWeapon.add(Texts.GAME_RELOAD_WEAPON + "5s"); victim.getWorld().dropItemNaturally(victim.getLocation(), setName(new ItemStack(Material.WOOD_HOE, 1), "§2Gun", lsWeapon, 1)); victim.setItemInHand(new ItemStack(Material.AIR)); } p.playSound(victim.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 3, 1); victim.playSound(victim.getLocation(), Sound.ENTITY_VILLAGER_DEATH, 3, 1); victim.sendMessage(Texts.PRE_TEXT + Texts.GAME_DEATH); playerDeath(victim); // Last one alive? int playersAlive = 0; for (Player players : getPlayerInArena(getPlayersArena(p))) { if (playerIsAlive(players)) playersAlive++; } if (playersAlive < 2) { for (Player p : getPlayerInArena(getPlayersArena(victim))) { p.sendMessage(Texts.PRE_TEXT + Texts.GAME_MURDERER_WINS); p.playSound(p.getLocation(), Sound.ENTITY_ENDERDRAGON_GROWL, 3, 1); } stopGame(getPlayersArena(p), true); } i.setVelocity(p.getLocation().getDirection().zero()); cancel(); } } } } }; runnable.runTaskTimer(this, 1, 1); p.getWorld().playSound(e.getPlayer().getLocation(), Sound.ENTITY_ENDERDRAGON_HURT, (float) 0.5, 1); BukkitRunnable runnableWeaponBack = new BukkitRunnable() { int ticksUntilWeaponBack = 20 * 20; @Override public void run() { if (ticksUntilWeaponBack == 0) { if (!p.getInventory().contains(Material.STONE_AXE) && getGameStarted(getPlayersArena(p)) && playerIsAlive(p)) { p.getInventory().setHeldItemSlot(1); List<String> lsKnife = new ArrayList<>(); lsKnife.add(Texts.GAME_HOWTO_KNIFE); p.getInventory().addItem(setName(new ItemStack(Material.STONE_AXE, 1), "§2Knife", lsKnife, 1)); List<Entity> entList = p.getWorld().getEntities(); for (Entity current : entList) { if (current instanceof Item && ((Item) current).getItemStack().getType() == Material.STONE_AXE) { current.remove(); } } } cancel(); } else { ticksUntilWeaponBack--; } } }; runnableWeaponBack.runTaskTimer(this, 0, 1); } } } // It's the gun! Throw the bullet! if (getPlayerInGame(e.getPlayer()) && e.getPlayer().getItemInHand().getType() == Material.WOOD_HOE && getGameStarted(getPlayersArena(e.getPlayer()))) { if (e.getAction() == Action.RIGHT_CLICK_AIR || (e.getAction() == Action.RIGHT_CLICK_BLOCK && e.getClickedBlock().getType() != Material.WOOD_BUTTON)) { if (e.getPlayer().getItemInHand().hasItemMeta() && e.getPlayer().getItemInHand().getItemMeta().getDisplayName().equals("§2Gun")) { Player p = e.getPlayer(); if (System.currentTimeMillis() - (reloadTime.get(e.getPlayer().getName())) >= 5000) { Vector vec = p.getLocation().getDirection().multiply(5); Snowball ball = p.getWorld().spawn(p.getEyeLocation(), Snowball.class); ball.setShooter(p); ball.setVelocity(vec); e.getPlayer().getWorld().playSound(e.getPlayer().getLocation(), Sound.ENTITY_ENDERDRAGON_HURT, 1, 1); reloadTime.put(p.getName(), System.currentTimeMillis()); } else { p.playSound(p.getLocation(), Sound.UI_BUTTON_CLICK, 1, 1); } } } } // Do not allow anything else except WOOD_BUTTON if (getPlayerInGame(e.getPlayer())) { // Its a wooden button! if (!(e.getAction() == Action.RIGHT_CLICK_BLOCK && e.getClickedBlock() != null && e.getClickedBlock().getType() == Material.WOOD_BUTTON)) { e.setCancelled(true); } } // Player clicked a block. If this is a join-sign, join! if (e.getAction() == Action.RIGHT_CLICK_BLOCK && e.getClickedBlock() != null && isSign(e.getClickedBlock())) { Sign theSign = (Sign) e.getClickedBlock().getState(); if (theSign.getLine(0).equals(ChatColor.GREEN + "[Murder]")) { for (int i = 1; i < 100; i++) { if (theSign.getLine(3).startsWith(ChatColor.BLUE + "A" + i + ": ")) { e.getPlayer().performCommand("mcm join " + i); } } // Teleport player to the lobby if (theSign.getLine(2).equals(ChatColor.DARK_GREEN + "--> Lobby <--")) { if (getPlayerInGame(e.getPlayer())) { playersList.remove(e.getPlayer()); playersTeam.remove(e.getPlayer().getName()); playersMap.remove(e.getPlayer().getName()); } e.getPlayer().performCommand("mcm lobby"); for (Player player : getPlayerInArena(getPlayersArena(e.getPlayer()))) { player.sendMessage(Texts.PRE_TEXT + "§6" + e.getPlayer().getDisplayName() + Texts.GAME_PLAYER_LEFT); } } } } } @EventHandler public void onHit(EntityDamageByEntityEvent e) { // Killed by murderer if (e.getEntity() instanceof Player && e.getDamager() instanceof Player && getPlayerInGame((Player) e.getEntity()) && getPlayerInGame((Player) e.getDamager())) { Player victim = (Player) e.getEntity(); Player damager = (Player) e.getDamager(); if (playerIsMurderer(damager) && damager.getItemInHand().getType() == Material.STONE_AXE && playerIsAlive(victim)) { if (victim.getInventory().contains(Material.WOOD_HOE)) { List<String> lsWeapon = new ArrayList<>(); lsWeapon.add(Texts.GAME_HOWTO_WEAPON); lsWeapon.add(Texts.GAME_RELOAD_WEAPON + "5s"); victim.getWorld().dropItemNaturally(victim.getLocation(), setName(new ItemStack(Material.WOOD_HOE, 1), "§2Gun", lsWeapon, 1)); victim.setItemInHand(new ItemStack(Material.AIR)); } damager.playSound(victim.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 3, 1); victim.playSound(victim.getLocation(), Sound.ENTITY_VILLAGER_DEATH, 3, 1); victim.sendMessage(Texts.PRE_TEXT + Texts.GAME_DEATH); playerDeath(victim); // Last one alive? int playersAlive = 0; for (Player players : getPlayerInArena(getPlayersArena(damager))) { if (playerIsAlive(players)) playersAlive++; } if (playersAlive < 2) { for (Player p : getPlayerInArena(getPlayersArena(victim))) { p.sendMessage(Texts.PRE_TEXT + Texts.GAME_MURDERER_WINS); p.playSound(p.getLocation(), Sound.ENTITY_ENDERDRAGON_GROWL, 3, 1); } stopGame(getPlayersArena(damager), true); } } e.setCancelled(true); return; } if (e.getDamager() instanceof Snowball && e.getEntity() instanceof Player && getPlayerInGame((Player) e.getEntity())) { // A player shot you final Player damager = (Player) ((Snowball) e.getDamager()).getShooter(); final Player victim = (Player) e.getEntity(); if (playerIsMurderer(victim)) { // Killed the murderer! for (Player p : getPlayerInArena(getPlayersArena(victim))) { p.sendMessage(Texts.PRE_TEXT + Texts.GAME_KILLED_MURDERER.replace("%killer", damager.getDisplayName())); p.playSound(p.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 3, 1); } victim.playSound(victim.getLocation(), Sound.ENTITY_VILLAGER_DEATH, 3, 1); playerDeath(victim); stopGame(getPlayersArena(victim), true); } else if ((playerIsBystander(victim) || playerIsBystanderWithWeapon(victim)) && playerIsAlive(victim)) { // Killed a bystander... damager.sendMessage(Texts.PRE_TEXT + Texts.GAME_KILLED_BYSTANDER); victim.sendMessage(Texts.PRE_TEXT + Texts.GAME_KILLED_BY_BYSTANDER); if (damager.getInventory().contains(Material.WOOD_HOE)) { List<String> lsWeapon = new ArrayList<>(); lsWeapon.add(Texts.GAME_HOWTO_WEAPON); lsWeapon.add(Texts.GAME_RELOAD_WEAPON + "5s"); damager.getWorld().dropItemNaturally(damager.getLocation(), setName(new ItemStack(Material.WOOD_HOE, 1), "§2Gun", lsWeapon, 1)); damager.setItemInHand(new ItemStack(Material.AIR)); reloadTime.put(damager.getName(), System.currentTimeMillis()); } victim.playSound(victim.getLocation(), Sound.ENTITY_VILLAGER_DEATH, 3, 1); damager.playSound(damager.getLocation(), Sound.ENTITY_GHAST_HURT, 3, 1); damager.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 20 * 20, 50)); damager.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 20 * 20, 1)); playerDeath(victim); } e.setCancelled(true); } } private void playerDeath(Player p) { p.getLocation().getWorld().playEffect(p.getLocation(), Effect.STEP_SOUND, Material.REDSTONE_WIRE); playersAlive.put(p.getName(), false); p.getInventory().clear(); p.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 2 * 20, 50)); p.removePotionEffect(PotionEffectType.SLOW); p.setAllowFlight(true); for (Player playersInMap : getPlayerInArena(getPlayersArena(p))) { playersInMap.hidePlayer(p); } } @EventHandler public void onEntityDamage(EntityDamageEvent e) { if (e.getEntity() instanceof Player && getPlayerInGame((Player) e.getEntity())) { Player p = (Player) e.getEntity(); // No fall-damage, suicide or drowning while in-arena but not in-game! if ((e.getCause().equals(EntityDamageEvent.DamageCause.FALL) || e.getCause().equals(EntityDamageEvent.DamageCause.SUICIDE) || e.getCause().equals(EntityDamageEvent.DamageCause.DROWNING) || e.getCause().equals(EntityDamageEvent.DamageCause.FIRE) || e.getCause().equals(EntityDamageEvent.DamageCause.FIRE_TICK)) && (countdown.get(getPlayersArena(p)) != -1 || getPlayerInArena(getPlayersArena(p)).size() == 1) || !playerIsAlive(p)) { e.setCancelled(true); } else if ((e.getCause().equals(EntityDamageEvent.DamageCause.FALL) || e.getCause().equals(EntityDamageEvent.DamageCause.SUICIDE) || e.getCause().equals(EntityDamageEvent.DamageCause.DROWNING) || e.getCause().equals(EntityDamageEvent.DamageCause.FIRE) || e.getCause().equals(EntityDamageEvent.DamageCause.FIRE_TICK)) && playerIsAlive(p)) { if ((p.getHealth() - e.getDamage()) <= 0) { if (playerIsMurderer(p)) { for (Player players : getPlayerInArena(getPlayersArena(p))) { players.sendMessage(Texts.PRE_TEXT + Texts.GAME_KILLED_MURDERER.replace("%killer", e.getCause().toString())); players.playSound(p.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 3, 1); } stopGame(getPlayersArena(p), true); } else { if (p.getInventory().contains(Material.WOOD_HOE)) { List<String> lsWeapon = new ArrayList<>(); lsWeapon.add(Texts.GAME_HOWTO_WEAPON); lsWeapon.add(Texts.GAME_RELOAD_WEAPON + "5s"); p.getWorld().dropItemNaturally(p.getLocation(), setName(new ItemStack(Material.WOOD_HOE, 1), "§2Gun", lsWeapon, 1)); p.setItemInHand(new ItemStack(Material.AIR)); reloadTime.put(p.getName(), System.currentTimeMillis()); } p.playSound(p.getLocation(), Sound.ENTITY_VILLAGER_DEATH, 3, 1); p.sendMessage(Texts.PRE_TEXT + Texts.GAME_KILLED_BY_UNKNOWN); playerDeath(p); // Last one alive? int playersAlive = 0; for (Player players : getPlayerInArena(getPlayersArena(p))) { if (playerIsAlive(players)) playersAlive++; } if (playersAlive < 2) { for (Player players : getPlayerInArena(getPlayersArena(p))) { players.sendMessage(Texts.PRE_TEXT + Texts.GAME_MURDERER_WINS); players.playSound(p.getLocation(), Sound.ENTITY_ENDERDRAGON_GROWL, 3, 1); } stopGame(getPlayersArena(p), true); } } p.setHealth(20); e.setCancelled(true); } } } } @EventHandler public void onPlayerLeave(PlayerQuitEvent e) { Player p = e.getPlayer(); playerLeave(p); } @EventHandler public void onBlockBreak(BlockBreakEvent e) { // No block-breaking in-game! if (getPlayerInGame(e.getPlayer())) e.setCancelled(true); } @EventHandler public void playerDropItem(PlayerDropItemEvent e) { // Why would you want to drop your weapons?! if (getPlayerInGame(e.getPlayer())) e.setCancelled(true); } @EventHandler public void playerPickupItem(PlayerPickupItemEvent e) { // The Murderer is not allowed to pick up the gun + he is the only one who is allowed to pick up the knife if (getPlayerInGame(e.getPlayer())) { if (e.getItem().getItemStack().getType() == Material.STONE_AXE && playerIsAlive(e.getPlayer()) && playerIsMurderer(e.getPlayer())) { e.setCancelled(false); } else if (e.getItem().getItemStack().getType() == Material.WOOD_HOE && playerIsAlive(e.getPlayer()) && (playerIsBystander(e.getPlayer()) || playerIsBystanderWithWeapon(e.getPlayer())) && System.currentTimeMillis() - (reloadTime.get(e.getPlayer().getName())) >= 20000) { e.setCancelled(false); } else { e.setCancelled(true); } } } /** * Manages the countdowns in every arena */ private void countdown() { getServer().getScheduler().scheduleSyncRepeatingTask(this, () -> { for (int i = 1; i < 100; i++) { if (countdown.get(i) != -1) { if (countdown.get(i) != 0) { if (getPlayerInArena(i).size() < 2) { for (Player players : getPlayerInArena(i)) { players.sendMessage(Texts.PRE_TEXT + Texts.GAME_START_STOPPED); players.setLevel(0); } countdown.put(i, -1); return; } if (countdown.get(i) < 6) { for (Player players : getPlayerInArena(i)) { players.playSound(players.getLocation(), Sound.UI_BUTTON_CLICK, 3, 1); } } for (Player players : getPlayerInArena(i)) { players.setLevel(countdown.get(i)); } countdown.put(i, countdown.get(i) - 1); } else { countdown.put(i, countdown.get(i) - 1); if (getPlayerInArena(i).size() < 2) { for (Player players : getPlayerInArena(i)) { players.sendMessage(Texts.PRE_TEXT + Texts.GAME_START_STOPPED); players.setLevel(countdown.get(0)); } countdown.put(i, -1); return; } startGame(i); } } } }, 0, 20L); } /** * Shows the time until player is able to shoot again in the exp-bar */ private void reloadTime() { getServer().getScheduler().scheduleSyncRepeatingTask(this, () -> { for (Player p : playersList) { long time = System.currentTimeMillis() - reloadTime.get(p.getName()); if (time < 500) { p.setExp((float) 1); } else if (time < 1000) { p.setExp((float) 0.9); } else if (time < 1500) { p.setExp((float) 0.8); } else if (time < 2000) { p.setExp((float) 0.7); } else if (time < 2500) { p.setExp((float) 0.6); } else if (time < 3000) { p.setExp((float) 0.5); } else if (time < 3500) { p.setExp((float) 0.4); } else if (time < 4000) { p.setExp((float) 0.3); } else if (time < 4500) { p.setExp((float) 0.2); } else if (time < 5000) { p.setExp((float) 0.1); } else { p.setExp((float) 0.0); } } }, 0, 1); } /** * Updates the signs every half second and shows game-status and player-count */ private void updateSigns() { getServer().getScheduler().scheduleSyncRepeatingTask(this, () -> { for (Map.Entry<Integer, Block> b : updateSigns.entrySet()) { if (isSign(b.getValue())) { // Load chunk, prevent NullPointerExceptions b.getValue().getChunk().load(); Sign mySign; try { mySign = (Sign) b.getValue().getState(); } catch (NullPointerException e) { Bukkit.getLogger().warning("Signs' chunk not loaded! Will update later..."); continue; } if (!arenaConfig.get(b.getKey())) { mySign.setLine(1, ChatColor.RED + "Disabled"); mySign.setLine(2, ChatColor.RED + "0 / " + maxPlayers); mySign.update(); } else { mySign.setLine(1, getArenaStatus(b.getKey())); mySign.setLine(2, ChatColor.RED + "" + getPlayerInArena(b.getKey()).size() + " / " + maxPlayers); mySign.update(); } } } }, 0, 10L); } @EventHandler public void onSignChange(SignChangeEvent event) { // A Murder-sign? Change and save it! if (event.getLine(0).trim().equalsIgnoreCase("Murder")) { for (int i = 1; i < 100; i++) { if (event.getLine(2).equalsIgnoreCase("mcm join " + i) && event.getPlayer().isOp()) { event.setLine(0, ChatColor.GREEN + "[Murder]"); event.setLine(1, ""); event.setLine(2, ChatColor.RED + "0 / " + maxPlayers); event.setLine(3, ChatColor.BLUE + "A" + i + ": " + event.getLine(3)); List<Double> listPosition = Arrays.asList(event.getBlock().getLocation().getX(), event.getBlock().getLocation().getY(), event.getBlock().getLocation().getZ()); getConfig().set("maps." + i + ".signWorld", event.getPlayer().getWorld().getName()); getConfig().set("maps." + i + ".sign", listPosition); saveConfig(); loadConfig(); } } } // A Murder-lobby-sign? Change and save it! if (event.getLine(0).equalsIgnoreCase("Murder") && event.getLine(2).equalsIgnoreCase("mcm lobby") && event.getPlayer().isOp()) { event.setLine(0, ChatColor.GREEN + "[Murder]"); event.setLine(2, ChatColor.DARK_GREEN + "--> Lobby <--"); } } /** * Create an ItemStack with more information * * @param is New ItemStack * @param name Name of item * @param lore Sub-titles of item * @param amount Amount of items * @return Custom ItemStack */ private ItemStack setName(ItemStack is, String name, List<String> lore, int amount) { ItemMeta im = is.getItemMeta(); if (name != null) im.setDisplayName(name); if (lore != null) im.setLore(lore); is.setItemMeta(im); is.setAmount(amount); return is; } /** * Is this block a sign? * * @param theBlock Block to check * @return Is this block a sign */ private boolean isSign(Block theBlock) { return theBlock.getType() == Material.SIGN || theBlock.getType() == Material.SIGN_POST || theBlock.getType() == Material.WALL_SIGN; } /** * Get a random spawn of an arena * * @param mapId Which map / arena * @return A random spawn */ private Location randomSpawn(int mapId) { Random r = new Random(); int random = r.nextInt(8) + 1; List<Double> spawns = this.getConfig().getDoubleList("maps." + mapId + "." + random); return new Location(getServer().getWorld(gameWorldPrefix + mapId), spawns.get(0), spawns.get(1), spawns.get(2)); } /** * Get the lobby-location * * @return Lobby-location */ public Location mcmSpawn() { List<Double> spawn = getConfig().getDoubleList("lobbySpawn"); return new Location(Bukkit.getWorld(getConfig().getString("lobbyWorld")), spawn.get(0), spawn.get(1), spawn.get(2)); } /** * Did the game start? * * @param mapId Which map / arena will be checked * @return If the game already started or not */ public boolean getGameStarted(int mapId) { return gameStarted.get(mapId); } /** * Get a list of every player in an arena * * @param map Which map / arena will be checked * @return A list of every player in the arena */ public List<Player> getPlayerInArena(int map) { List<Player> myPlayers = new ArrayList<>(); for (Player p : playersList) { if (playersMap.get(p.getName()).equals(map)) { myPlayers.add(p); } } return myPlayers; } /** * Get the arena of a specific player * * @param p Which player will be checked * @return Arena of the player or 0 if there is none */ public int getPlayersArena(Player p) { if (playersMap.containsKey(p.getName())) { return playersMap.get(p.getName()); } return 0; } /** * Is the player currently in-game? * * @param p Which player will be checked * @return If the player is currently in-game */ public boolean getPlayerInGame(Player p) { return playersList.contains(p); } /** * Is the player the murderer? * * @param p Which player will be checked * @return If the player is the murderer */ private boolean playerIsMurderer(Player p) { return playersTeam.containsKey(p.getName()) && playersTeam.get(p.getName()).equals("murderer"); } /** * Is the player a bystander? * * @param p Which player will be checked * @return If the player is a bystander */ private boolean playerIsBystander(Player p) { return playersTeam.containsKey(p.getName()) && playersTeam.get(p.getName()).equals("bystander"); } /** * Is the player the bystander with a secret weapon? * * @param p Which player will be checked * @return If the player is the bystander with a secret weapon */ private boolean playerIsBystanderWithWeapon(Player p) { return playersTeam.containsKey(p.getName()) && playersTeam.get(p.getName()).equals("bystanderWeapon"); } /** * Is the player alive? * * @param p Which player will be checked * @return If the player is alive */ private boolean playerIsAlive(Player p) { return playersAlive.containsKey(p.getName()) && playersAlive.get(p.getName()); } /** * Get the current game-status of an arena * * @param mapId Which map / arena will be checked * @return State of game */ private String getArenaStatus(int mapId) { if (getGameStarted(mapId)) { return ChatColor.RED + "In-Game"; } if (countdown.get(mapId) == -1) { return ChatColor.GREEN + "Waiting"; } if (countdown.get(mapId) != -1) { return ChatColor.DARK_GREEN + "Countdown"; } return "unknown"; } }