aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/MylesAndMore/tumble
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/MylesAndMore/tumble')
-rw-r--r--src/main/java/com/MylesAndMore/tumble/EventListener.java296
-rw-r--r--src/main/java/com/MylesAndMore/tumble/Game.java597
-rw-r--r--src/main/java/com/MylesAndMore/tumble/Main.java39
-rw-r--r--src/main/java/com/MylesAndMore/tumble/TumbleManager.java33
-rw-r--r--src/main/java/com/MylesAndMore/tumble/api/Generator.java120
-rw-r--r--src/main/java/com/MylesAndMore/tumble/api/Layers.java373
-rw-r--r--src/main/java/com/MylesAndMore/tumble/api/Metrics.java865
-rw-r--r--src/main/java/com/MylesAndMore/tumble/commands/ReloadCommand.java24
-rw-r--r--src/main/java/com/MylesAndMore/tumble/commands/SetAutoStart.java97
-rw-r--r--src/main/java/com/MylesAndMore/tumble/commands/SetWinnerLoc.java115
-rw-r--r--src/main/java/com/MylesAndMore/tumble/commands/SetWorldConfig.java83
-rw-r--r--src/main/java/com/MylesAndMore/tumble/commands/StartGame.java93
12 files changed, 0 insertions, 2735 deletions
diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java
deleted file mode 100644
index 63ca9a0..0000000
--- a/src/main/java/com/MylesAndMore/tumble/EventListener.java
+++ /dev/null
@@ -1,296 +0,0 @@
-package com.MylesAndMore.tumble;
-
-import java.util.Objects;
-
-import org.bukkit.Bukkit;
-import org.bukkit.Material;
-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.BlockDropItemEvent;
-import org.bukkit.event.entity.*;
-import org.bukkit.event.inventory.InventoryDragEvent;
-import org.bukkit.event.player.*;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.util.Vector;
-
-/**
- * Tumble event listener for all plugin and game-related events.
- */
-public class EventListener implements Listener {
- @EventHandler
- public void PlayerJoinEvent(PlayerJoinEvent event) {
- // On a PlayerJoinEvent, check if the config is set to hide the join/leave
- // messages
- // If true, null out the join message (which just makes it so that there is no
- // message)
- // If false, nothing will happen, and the default message will display
- if (TumbleManager.getPlugin().getConfig().getBoolean("hideJoinLeaveMessages")) {
- event.setJoinMessage(null);
- }
- // Check if either of the worlds are not defined in config, if so, end
- // This is to avoid NPEs and such
- if (TumbleManager.getGameWorld() == null || TumbleManager.getLobbyWorld() == null) {
- return;
- }
- // Check if the player joining is in the game world, if true then
- if (event.getPlayer().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) {
- // send them back to the lobby.
- event.getPlayer().teleport(Bukkit.getWorld(TumbleManager.getLobbyWorld()).getSpawnLocation());
- }
- // For auto-start function: check if the autoStart is enabled
- if (TumbleManager.getPlugin().getConfig().getBoolean("autoStart.enabled")) {
- // If so, check if the amount of players has been reached
- if (TumbleManager.getPlayersInLobby().size() == TumbleManager.getPlugin().getConfig().getInt("autoStart.players")) {
- // The autoStart should begin; pass this to the Game
- Game.getGame().autoStart();
- }
- }
- }
-
- @EventHandler
- public void PlayerChangedWorldEvent(PlayerChangedWorldEvent event) {
- if (TumbleManager.getGameWorld() == null || TumbleManager.getLobbyWorld() == null) {
- return;
- }
- // Check if the player changed to the lobbyWorld, then
- if (event.getPlayer().getWorld() == Bukkit.getWorld(TumbleManager.getLobbyWorld())) {
- // run the autostart checks (commented above)
- if (TumbleManager.getPlugin().getConfig().getBoolean("autoStart.enabled")) {
- if (TumbleManager.getPlayersInLobby().size() == TumbleManager.getPlugin().getConfig().getInt("autoStart.players")) {
- Game.getGame().autoStart();
- }
- }
- }
- // also check if the player left to another world
- else if (event.getFrom() == Bukkit.getWorld(TumbleManager.getLobbyWorld())) {
- if (Objects.equals(Game.getGame().getGameState(), "waiting")) {
- Game.getGame().cancelStart();
- }
- }
- }
-
- @EventHandler
- public void PlayerQuitEvent(PlayerQuitEvent event) {
- // On a PlayerQuitEvent, check if the config is set to hide the join/leave
- // messages
- // If true, null out the quit message (which just makes it so that there is no
- // message)
- // If false, nothing will happen, and the default message will display
- if (TumbleManager.getPlugin().getConfig().getBoolean("hideJoinLeaveMessages")) {
- event.setQuitMessage(null);
- }
- if (TumbleManager.getLobbyWorld() == null) {
- return;
- }
- if (event.getPlayer().getWorld() == Bukkit.getWorld(TumbleManager.getLobbyWorld())) {
- // Check if the game is in the process of autostarting
- if (Objects.equals(Game.getGame().getGameState(), "waiting")) {
- // Cancel the autostart
- Game.getGame().cancelStart();
- }
- }
- }
-
- @EventHandler
- public void PlayerDeathEvent(PlayerDeathEvent event) {
- if (TumbleManager.getGameWorld() == null) {
- return;
- }
- // On a PlayerDeathEvent,
- // check to see if the player died in the gameWorld,
- if (event.getEntity().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) {
- // then pass this off to the Game
- Game.getGame().playerDeath(event.getEntity());
- }
- }
-
- @EventHandler
- public void PlayerItemDamageEvent(PlayerItemDamageEvent event) {
- if (TumbleManager.getGameWorld() == null) {
- return;
- }
- // On an ItemDamageEvent
- // check to see if the item was damaged in the gameWorld,
- if (event.getPlayer().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) {
- event.setCancelled(true);
- }
- }
-
- // private long lastTimeP;
- @EventHandler
- public void ProjectileLaunchEvent(ProjectileLaunchEvent event) {
- if (TumbleManager.getGameWorld() == null) {
- return;
- }
- // When a projectile is launched,
- // check to see if projectile was thrown in the gameWorld.
- if (event.getEntity().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) {
- if (event.getEntity() instanceof Snowball) {
- if (event.getEntity().getShooter() instanceof Player player) {
- // Check to see if the last snowball was thrown less than 200ms ago, if so, don't allow another
- // if ((System.currentTimeMillis() - lastTimeP) < 200) { event.setCancelled(true); }
- // else {
- // // Otherwise, continue with logic
- // lastTimeP = System.currentTimeMillis();
- // // This prevents players from shooting snowballs before the game actually begins
- if (Objects.equals(Game.getGame().getGameState(), "starting")) {
- event.setCancelled(true);
- }
- else {
- // This gives players a snowball when they've used one
- Bukkit.getServer().getScheduler().runTask(TumbleManager.getPlugin(), () -> {
- player.getInventory().addItem(new ItemStack(Material.SNOWBALL, 1));
- });
- }
- // }
- }
- }
- }
- }
-
- @EventHandler
- public void ProjectileHitEvent(ProjectileHitEvent event) {
- if (TumbleManager.getGameWorld() == null) {
- return;
- }
- // Weird stacktrace thing
- else if (event.getHitBlock() == null) {
- return;
- }
- // When a projectile hits
- // check to see if the projectile hit in the gameWorld,
- if (event.getHitBlock().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) {
- // then check if the projectile was a snowball,
- if (event.getEntity() instanceof Snowball) {
- // then check if a player threw it,
- if (event.getEntity().getShooter() instanceof Player shooterPlayer) {
- // then check to see if it hit a player or a block
- if (event.getHitBlock() != null) {
- // if it was a block, check if that block is within the game area,
- if (event.getHitBlock().getLocation().distanceSquared(Bukkit.getWorld(TumbleManager.getGameWorld()).getSpawnLocation()) < 579) {
- // then remove that block.
- event.getHitBlock().setType(Material.AIR);
- }
- }
- else if (event.getHitEntity() != null) {
- // if it was an entity, check if it hit a player,
- if (event.getHitEntity() instanceof Player hitPlayer) {
- // then cancel the knockback (has to be delayed by a tick for some reason)
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- hitPlayer.setVelocity(new Vector());
- });
- }
- }
- }
- }
- }
- }
-
- @EventHandler
- public void PlayerDropItemEvent(PlayerDropItemEvent event) {
- if (TumbleManager.getGameWorld() == null) {
- return;
- }
- // When an item is dropped,
- // check if the item was dropped in the game world
- if (event.getPlayer().getWorld() == Bukkit.getWorld((TumbleManager.getGameWorld()))) {
- event.setCancelled(true);
- }
- }
-
- @EventHandler
- public void PlayerMoveEvent(PlayerMoveEvent event) {
- if (TumbleManager.getGameWorld() == null) {
- return;
- }
- // On a PlayerMoveEvent, check if the game is starting
- if (Objects.equals(Game.getGame().getGameState(), "starting")) {
- // Cancel the event if the game is starting (so players can't move before the game starts)
- event.setCancelled(true);
- }
- }
-
- @EventHandler
- public void BlockDropItemEvent(BlockDropItemEvent event) {
- if (TumbleManager.getGameWorld() == null) {
- return;
- }
- // If a block was going to drop an item (ex. snow dropping snowballs) in the GameWorld, cancel it
- if (event.getBlock().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) {
- event.setCancelled(true);
- }
- }
-
- // private long lastTimeI;
- @EventHandler
- public void PlayerInteractEvent(PlayerInteractEvent event) {
- if (TumbleManager.getGameWorld() == null) {
- return;
- }
- // Check if a player was left clicking a block in the gameWorld
- if (event.getAction() == Action.LEFT_CLICK_BLOCK) {
- if (event.getClickedBlock().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) {
- // Then check to see if the player interacted less than 150ms ago
- // if ((System.currentTimeMillis() - lastTimeI) < 150) return;
- // If not, set that block to air (break it)
- // else {
- // lastTimeI = System.currentTimeMillis();
- event.getClickedBlock().setType(Material.AIR);
- // }
- }
- }
- }
-
- @EventHandler
- public void BlockBreakEvent(BlockBreakEvent event) {
- if (TumbleManager.getGameWorld() == null) {
- return;
- }
- // This just doesn't allow blocks to break in the gameWorld; the PlayerInteractEvent will take care of everything
- // It just keeps client commonality w/ animations and stuff
- if (event.getBlock().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) {
- event.setCancelled(true);
- }
- }
-
- @EventHandler
- public void FoodLevelChangeEvent(FoodLevelChangeEvent event) {
- if (TumbleManager.getGameWorld() == null) {
- return;
- }
- // When someone's food level changes, check if that happened in the gameWorld, then cancel it
- if (event.getEntity().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) {
- event.setCancelled(true);
- }
- }
-
- @EventHandler
- public void EntityDamageEvent(EntityDamageEvent event) {
- if (TumbleManager.getGameWorld() == null) {
- return;
- }
- // Check to see if a player got damaged by another entity (player, snowball, etc) in the gameWorld, if so, cancel it
- if (event.getEntity().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) {
- if (event.getEntity() instanceof Player) {
- if (event.getCause() == EntityDamageEvent.DamageCause.ENTITY_ATTACK || event.getCause() == EntityDamageEvent.DamageCause.ENTITY_SWEEP_ATTACK || event.getCause() == EntityDamageEvent.DamageCause.FALL) {
- event.setCancelled(true);
- }
- }
- }
- }
-
- @EventHandler
- public void InventoryDragEvent(InventoryDragEvent event) {
- if (TumbleManager.getGameWorld() == null) {
- return;
- }
- if (event.getWhoClicked().getWorld() == Bukkit.getWorld((TumbleManager.getGameWorld()))) {
- event.setCancelled(true);
- }
- }
-
-}
diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java
deleted file mode 100644
index 1400887..0000000
--- a/src/main/java/com/MylesAndMore/tumble/Game.java
+++ /dev/null
@@ -1,597 +0,0 @@
-package com.MylesAndMore.tumble;
-
-import com.MylesAndMore.tumble.api.Generator;
-
-import com.MylesAndMore.tumble.api.Layers;
-import net.md_5.bungee.api.ChatMessageType;
-import net.md_5.bungee.api.chat.TextComponent;
-
-import org.bukkit.*;
-import org.bukkit.enchantments.Enchantment;
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.Item;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-import org.jetbrains.annotations.NotNull;
-
-import javax.annotation.Nullable;
-import java.util.*;
-
-/**
- * This class holds all methods relating to the tumble Game in any way!
- */
-public class Game {
- // Singleton class logic
- // Define the gameInstance
- private static Game gameInstance;
-
- // Private Game() constructor for singleton instance
- private Game() {
- gameWorld = Bukkit.getWorld(TumbleManager.getGameWorld());
- gameSpawn = gameWorld.getSpawnLocation();
- }
-
- // ONLY Public method to get the game instance
- public static Game getGame() {
- if (gameInstance == null) {
- gameInstance = new Game();
- }
- return gameInstance;
- }
-
-
- // Define local game vars
- // The gameState keeps the current state of the game (I'm so creative, I know)
- private String gameState;
- // Define a variable for the gameType
- private String gameType;
- // Define a variable for the game ID
- private int gameID = -1;
- // Define a variable for the autostart PID
- private int autoStartID = -1;
- // Define a variable to keep the list of tracks that have already played in the game
- List<String> sounds = new ArrayList<>();
-
- // Initialize a new instance of the Random class for use later
- private final Random Random = new Random();
- // Define the game world and its spawnpoint as a new Location for use later
- private final World gameWorld;
- private final Location gameSpawn;
- // Make a list of the game's players for later
- private List<Player> gamePlayers;
- // Make a list of the round's players
- private List<Player> roundPlayers;
- // Initialize a list to keep track of wins between rounds
- private List<Integer> gameWins;
-
-
- // BEGIN PUBLIC METHODS
-
- /**
- * Creates a new Game
- * @param type The type of game
- * @return true if the game succeeds creation, and false if not
- */
- public boolean startGame(@NotNull String type) {
- // Check if the game is starting or running, if so, do not start
- if (Objects.equals(gameState, "starting")) {
- return false;
- }
- else if (Objects.equals(gameState, "running")) {
- return false;
- }
- else {
- // Define the gameType
- switch (type) {
- case "shovels":
- case "snowballs":
- case "mixed":
- gameState = "starting";
- // Set the type to gameType since it won't change for this mode
- gameType = type;
- // Clear the players' inventories so they can't bring any items into the game
- clearInventories(TumbleManager.getPlayersInLobby());
- // Generate the correct layers for a Shovels game
- // The else statement is just in case the generator fails; this command will fail
- if (generateLayers(type)) {
- // Send all players from lobby to the game
- scatterPlayers(TumbleManager.getPlayersInLobby());
- } else {
- return false;
- }
- break;
- default:
- // The game type in the config did not match a specified game type; return false to signify that
- return false;
- }
- // If a game creation succeeded, then,
- // Update the game's players for later
- gamePlayers = new ArrayList<>(TumbleManager.getPlayersInGame());
- // Update the round's players for later
- roundPlayers = new ArrayList<>(TumbleManager.getPlayersInGame());
- // Create a list that will later keep track of each player's wins
- gameWins = new ArrayList<>();
- gameWins.addAll(List.of(0,0,0,0,0,0,0,0));
- // Put all players in spectator to prevent them from getting kicked for flying (this needs a delay bc servers are SLOOOWWW)
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- setGamemode(gamePlayers, GameMode.SPECTATOR);
- }, 25);
- // Wait 5s (100t) for the clients to load in
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- // Begin the countdown sequence
- playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 5, 1);
- displayTitles(gamePlayers, ChatColor.DARK_GREEN + "3", null, 3, 10, 7);
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 5, 1);
- displayTitles(gamePlayers, ChatColor.YELLOW + "2", null, 3, 10, 7);
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 5, 1);
- displayTitles(gamePlayers, ChatColor.DARK_RED + "1", null, 3, 10, 7);
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 5, 2);
- displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1);
- setGamemode(gamePlayers, GameMode.SURVIVAL);
- gameState = "running";
- }, 20);
- }, 20);
- }, 20);
- }, 100);
- }
- return true;
- }
-
- /**
- * Initiates an automatic start of a Tumble game
- */
- public void autoStart() {
- // Wait for the player to load in
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- gameState = "waiting";
- displayActionbar(TumbleManager.getPlayersInLobby(), ChatColor.GREEN + "Game will begin in 15 seconds!");
- playSound(TumbleManager.getPlayersInLobby(), Sound.BLOCK_NOTE_BLOCK_CHIME, SoundCategory.BLOCKS, 1, 1);
- TumbleManager.getMVWorldManager().loadWorld(TumbleManager.getGameWorld());
- // Schedule a process to start the game in 300t (15s) and save the PID so we can cancel it later if needed
- autoStartID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- startGame(TumbleManager.getGameType());
- }, 300);
- }, 50);
- }
-
- /**
- * Cancels a "waiting" automatic start
- */
- public void cancelStart() {
- Bukkit.getServer().getScheduler().cancelTask(Game.getGame().getAutoStartID());
- displayActionbar(TumbleManager.getPlayersInLobby(), ChatColor.RED + "Game start cancelled!");
- playSound(TumbleManager.getPlayersInLobby(), Sound.BLOCK_NOTE_BLOCK_BASS, SoundCategory.BLOCKS, 1, 1);
- gameState = null;
- autoStartID = -1;
- }
-
- /**
- * This method should be called on the death of one of the Game's players
- * @param player The player who died
- */
- public void playerDeath(Player player) {
- player.setGameMode(GameMode.SPECTATOR);
- // Add a delay to tp them to the gameWorld just in case they have a bed in another world
- // Delay is needed because instant respawn takes 1t
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- player.teleport(gameSpawn);
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- player.setGameMode(GameMode.SPECTATOR);
- }, 5);
- }, 5);
- // remove that player (who just died) from the roundPlayersArray, effectively eliminating them,
- roundPlayers.remove(player);
- // If there are less than 2 players in the game (1 just died),
- if (roundPlayers.size() < 2) {
- // End the game, passing the winner to the gameEnd method
- roundEnd(roundPlayers.get(0));
- }
- }
-
- // Methods to get the game type and game state for other classes outside the Game
-
- /**
- * @return The game's current state as a String ("waiting", "starting", "running", "complete")
- * Can also be null if not initialized.
- */
- public String getGameState() { return gameState; }
-
- /**
- * @return The Bukkit process ID of the autostart process, if applicable
- * Can also be null if not initialized, and -1 if the process failed to schedule.
- */
- public int getAutoStartID() { return autoStartID; }
-
-
- // BEGIN PRIVATE METHODS
-
- // Initialize Layers class
- private final Layers layers = new Layers();
- /**
- * Generates the layers in the gameWorld for a certain gameType
- * @param type can be either "shovels", "snowballs", or "mixed", anything else will fail generation
- * @return true if gameType was recognized and layers were (hopefully) generated, false if unrecognized
- */
- private boolean generateLayers(String type) {
- // Create a new Location for the layers to work with--this is so that we don't modify the actual gameSpawn var
- Location layer = new Location(gameSpawn.getWorld(), gameSpawn.getX(), gameSpawn.getY(), gameSpawn.getZ(), gameSpawn.getYaw(), gameSpawn.getPitch());
- if (Objects.equals(type, "shovels")) {
- layer.setY(layer.getY() - 1);
- // Choose a random type of generation; a circular layer, a square layer, or a multi-tiered layer of either variety
- if (Random.nextInt(4) == 0) {
- // Circular layer
- Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.SNOW_BLOCK), layers.getSafeMaterialList());
- }
- else if (Random.nextInt(4) == 1) {
- // Square layer
- Generator.generateClumps(Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 17, layer.getY(), layer.getZ() - 17), new Location(layer.getWorld(), layer.getX() + 17, layer.getY(), layer.getZ() + 17), Material.SNOW_BLOCK), layers.getSafeMaterialList());
- }
- else if (Random.nextInt(4) == 2) {
- // Multi-tiered circle
- Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.SNOW_BLOCK), layers.getSafeMaterialList());
- Generator.generateLayer(layer, 13, 1, Material.AIR);
- layer.setY(layer.getY() - 1);
- Generator.generateClumps(Generator.generateLayer(layer, 13, 1, Material.GRASS_BLOCK), layers.getMaterialList());
- Generator.generateLayer(layer, 4, 1, Material.AIR);
- layer.setY(layer.getY() - 1);
- Generator.generateClumps(Generator.generateLayer(layer, 4, 1, Material.PODZOL), layers.getMaterialList());
- }
- else {
- // Multi-tiered square
- Generator.generateClumps(Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 17, layer.getY(), layer.getZ() - 17), new Location(layer.getWorld(), layer.getX() + 17, layer.getY(), layer.getZ() + 17), Material.SNOW_BLOCK), layers.getSafeMaterialList());
- Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 13, layer.getY(), layer.getZ() - 13), new Location(layer.getWorld(), layer.getX() + 13, layer.getY(), layer.getZ() + 13), Material.AIR);
- layer.setY(layer.getY() - 1);
- Generator.generateClumps(Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 13, layer.getY(), layer.getZ() - 13), new Location(layer.getWorld(), layer.getX() + 13, layer.getY(), layer.getZ() + 13), Material.GRASS_BLOCK), layers.getMaterialList());
- Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 7, layer.getY(), layer.getZ() - 7), new Location(layer.getWorld(), layer.getX() + 7, layer.getY(), layer.getZ() + 7), Material.AIR);
- layer.setY(layer.getY() - 1);
- Generator.generateClumps(Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 7, layer.getY(), layer.getZ() - 7), new Location(layer.getWorld(), layer.getX() + 7, layer.getY(), layer.getZ() + 7), Material.PODZOL), layers.getMaterialList());
- }
- ItemStack shovel = new ItemStack(Material.IRON_SHOVEL);
- shovel.addEnchantment(Enchantment.SILK_TOUCH, 1);
- if (Objects.equals(gameState, "running")) {
- giveItems(TumbleManager.getPlayersInGame(), shovel);
- }
- else if (Objects.equals(gameState, "starting")) {
- giveItems(TumbleManager.getPlayersInLobby(), shovel);
- }
- // Schedule a process to give snowballs after 2m30s (so people can't island, the OG game had this)
- // Add 160t because of the countdown
- gameID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- clearInventories(gamePlayers);
- giveItems(gamePlayers, new ItemStack(Material.SNOWBALL));
- displayActionbar(gamePlayers, ChatColor.DARK_RED + "Showdown!");
- playSound(gamePlayers, Sound.ENTITY_ELDER_GUARDIAN_CURSE, SoundCategory.HOSTILE, 1, 1);
- // End the round in another 2m30s
- gameID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- roundEnd(null);
- }, 3000);
- }, 3160);
- }
- else if (Objects.equals(type, "snowballs")) {
- layer.setY(layer.getY() - 1);
- // Similar generation to shovels, except there are three layers
- if (Random.nextInt(4) == 0) {
- // Circular layer
- Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.STONE), layers.getSafeMaterialList());
- layer.setY(layer.getY() - 6);
- Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.STONE), layers.getMaterialList());
- layer.setY(layer.getY() - 6);
- Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.STONE), layers.getMaterialList());
- }
- else if (Random.nextInt(4) == 1) {
- // Square layer
- Generator.generateClumps(Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 17, layer.getY(), layer.getZ() - 17), new Location(layer.getWorld(), layer.getX() + 17, layer.getY(), layer.getZ() + 17), Material.STONE), layers.getSafeMaterialList());
- layer.setY(layer.getY() - 6);
- Generator.generateClumps(Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 17, layer.getY(), layer.getZ() - 17), new Location(layer.getWorld(), layer.getX() + 17, layer.getY(), layer.getZ() + 17), Material.STONE), layers.getMaterialList());
- layer.setY(layer.getY() - 6);
- Generator.generateClumps(Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 17, layer.getY(), layer.getZ() - 17), new Location(layer.getWorld(), layer.getX() + 17, layer.getY(), layer.getZ() + 17), Material.STONE), layers.getMaterialList());
- }
- else if (Random.nextInt(4) == 2) {
- // Multi-tiered circle
- Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.STONE), layers.getSafeMaterialList());
- Generator.generateLayer(layer, 13, 1, Material.AIR);
- layer.setY(layer.getY() - 1);
- Generator.generateClumps(Generator.generateLayer(layer, 13, 1, Material.GRANITE), layers.getMaterialList());
- Generator.generateLayer(layer, 4, 1, Material.AIR);
- layer.setY(layer.getY() - 1);
- Generator.generateClumps(Generator.generateLayer(layer, 4, 1, Material.LIME_GLAZED_TERRACOTTA), layers.getMaterialList());
- layer.setY(layer.getY() - 6);
-
- Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.STONE), layers.getSafeMaterialList());
- Generator.generateLayer(layer, 13, 1, Material.AIR);
- layer.setY(layer.getY() - 1);
- Generator.generateClumps(Generator.generateLayer(layer, 13, 1, Material.GRANITE), layers.getMaterialList());
- Generator.generateLayer(layer, 4, 1, Material.AIR);
- layer.setY(layer.getY() - 1);
- Generator.generateClumps(Generator.generateLayer(layer, 4, 1, Material.LIME_GLAZED_TERRACOTTA), layers.getMaterialList());
- layer.setY(layer.getY() - 6);
-
- Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.STONE), layers.getSafeMaterialList());
- Generator.generateLayer(layer, 13, 1, Material.AIR);
- layer.setY(layer.getY() - 1);
- Generator.generateClumps(Generator.generateLayer(layer, 13, 1, Material.GRANITE), layers.getMaterialList());
- Generator.generateLayer(layer, 4, 1, Material.AIR);
- layer.setY(layer.getY() - 1);
- Generator.generateClumps(Generator.generateLayer(layer, 4, 1, Material.LIME_GLAZED_TERRACOTTA), layers.getMaterialList());
- }
- else {
- // Multi-tiered square
- Generator.generateClumps(Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 17, layer.getY(), layer.getZ() - 17), new Location(layer.getWorld(), layer.getX() + 17, layer.getY(), layer.getZ() + 17), Material.STONE), layers.getSafeMaterialList());
- Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 13, layer.getY(), layer.getZ() - 13), new Location(layer.getWorld(), layer.getX() + 13, layer.getY(), layer.getZ() + 13), Material.AIR);
- layer.setY(layer.getY() - 1);
- Generator.generateClumps(Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 13, layer.getY(), layer.getZ() - 13), new Location(layer.getWorld(), layer.getX() + 13, layer.getY(), layer.getZ() + 13), Material.GRANITE), layers.getMaterialList());
- Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 7, layer.getY(), layer.getZ() - 7), new Location(layer.getWorld(), layer.getX() + 7, layer.getY(), layer.getZ() + 7), Material.AIR);
- layer.setY(layer.getY() - 1);
- Generator.generateClumps(Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 7, layer.getY(), layer.getZ() - 7), new Location(layer.getWorld(), layer.getX() + 7, layer.getY(), layer.getZ() + 7), Material.LIME_GLAZED_TERRACOTTA), layers.getMaterialList());
- layer.setY(layer.getY() - 6);
-
- Generator.generateClumps(Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 17, layer.getY(), layer.getZ() - 17), new Location(layer.getWorld(), layer.getX() + 17, layer.getY(), layer.getZ() + 17), Material.STONE), layers.getSafeMaterialList());
- Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 13, layer.getY(), layer.getZ() - 13), new Location(layer.getWorld(), layer.getX() + 13, layer.getY(), layer.getZ() + 13), Material.AIR);
- layer.setY(layer.getY() - 1);
- Generator.generateClumps(Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 13, layer.getY(), layer.getZ() - 13), new Location(layer.getWorld(), layer.getX() + 13, layer.getY(), layer.getZ() + 13), Material.GRANITE), layers.getMaterialList());
- Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 7, layer.getY(), layer.getZ() - 7), new Location(layer.getWorld(), layer.getX() + 7, layer.getY(), layer.getZ() + 7), Material.AIR);
- layer.setY(layer.getY() - 1);
- Generator.generateClumps(Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 7, layer.getY(), layer.getZ() - 7), new Location(layer.getWorld(), layer.getX() + 7, layer.getY(), layer.getZ() + 7), Material.LIME_GLAZED_TERRACOTTA), layers.getMaterialList());
- layer.setY(layer.getY() - 6);
-
- Generator.generateClumps(Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 17, layer.getY(), layer.getZ() - 17), new Location(layer.getWorld(), layer.getX() + 17, layer.getY(), layer.getZ() + 17), Material.STONE), layers.getSafeMaterialList());
- Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 13, layer.getY(), layer.getZ() - 13), new Location(layer.getWorld(), layer.getX() + 13, layer.getY(), layer.getZ() + 13), Material.AIR);
- layer.setY(layer.getY() - 1);
- Generator.generateClumps(Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 13, layer.getY(), layer.getZ() - 13), new Location(layer.getWorld(), layer.getX() + 13, layer.getY(), layer.getZ() + 13), Material.GRANITE), layers.getMaterialList());
- Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 7, layer.getY(), layer.getZ() - 7), new Location(layer.getWorld(), layer.getX() + 7, layer.getY(), layer.getZ() + 7), Material.AIR);
- layer.setY(layer.getY() - 1);
- Generator.generateClumps(Generator.generateCuboid(new Location(layer.getWorld(), layer.getX() - 7, layer.getY(), layer.getZ() - 7), new Location(layer.getWorld(), layer.getX() + 7, layer.getY(), layer.getZ() + 7), Material.LIME_GLAZED_TERRACOTTA), layers.getMaterialList());
- }
- if (Objects.equals(gameState, "running")) {
- giveItems(TumbleManager.getPlayersInGame(), new ItemStack(Material.SNOWBALL));
- }
- else if (Objects.equals(gameState, "starting")) {
- giveItems(TumbleManager.getPlayersInLobby(), new ItemStack(Material.SNOWBALL));
- }
- // End the round in 5m
- gameID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> roundEnd(null), 6160);
- }
- else if (Objects.equals(type, "mixed")) {
- // Randomly select either shovels or snowballs and re-run the method
- if (Random.nextInt(2) == 0) {
- generateLayers("shovels");
- } else {
- generateLayers("snowballs");
- }
- }
- // Game type was invalid
- else {
- return false;
- }
- return true;
- }
-
- /**
- * Distributes items to a provided list of players
- * @param players The player list for which to distribute the items to
- * @param itemStack The ItemStack to be distributed
- */
- private void giveItems(List<Player> players, ItemStack itemStack) {
- for (Player aPlayer : players) {
- // Get a singular player from the player list and give that player the specified item
- aPlayer.getInventory().addItem(itemStack);
- }
- }
-
- /**
- * Clears the inventories of a provided player list
- * @param players The player list for which to clear the inventories of
- */
- private void clearInventories(List<Player> players) {
- for (Player aPlayer : players) {
- aPlayer.getInventory().clear();
- }
- }
-
- /**
- * Sets the gamemodes of a provided list of players
- * @param players The player list for which to set the gamemodes of
- * @param gameMode The GameMode to set
- */
- private void setGamemode(List<Player> players, GameMode gameMode) {
- for (Player aPlayer : players) {
- // Get a singular player from the player list and set their gamemode to the specified gamemode
- aPlayer.setGameMode(gameMode);
- }
- }
-
- /**
- * Displays a customized title to a provided list of players
- * @param players The player list for which to show the titles to
- * @param title The top title text
- * @param subtitle The bottom title subtext (nullable)
- * @param fadeIn The fadeIn duration (in ticks)
- * @param stay The stay duration (in ticks)
- * @param fadeOut The fadeOut duration (in ticks)
- */
- private void displayTitles(List<Player> players, String title, @Nullable String subtitle, int fadeIn, int stay, int fadeOut) {
- for (Player aPlayer : players) {
- // Get a singular player from the player list and display them the specified title
- aPlayer.sendTitle(title, subtitle, fadeIn, stay, fadeOut);
- }
- }
-
- /**
- * Displays an actionbar message to a provided list of players
- * @param players The player list for which to display the actionbar to
- * @param message The provided message (String format)
- */
- private void displayActionbar(List<Player> players, String message) {
- for (Player aPlayer : players) {
- aPlayer.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message));
- }
- }
-
- /**
- * Plays a sound to a provided list of players
- * @param players The player list for which to play the sound to
- * @param sound The sound to play
- * @param category The category of the sound
- * @param volume The volume of the sound
- * @param pitch The pitch of the sound
- */
- private void playSound(@NotNull List<Player> players, @NotNull Sound sound, @NotNull SoundCategory category, float volume, float pitch) {
- for (Player aPlayer : players) {
- aPlayer.playSound(aPlayer, sound, category, volume, pitch);
- }
- }
-
- /**
- * Teleports a list of players to the specified scatter locations in the gameWorld
- * @param players a List of Players to teleport
- */
- private void scatterPlayers(List<Player> players) {
- // Get the coords of the game's spawn location
- double x = gameSpawn.getX();
- double y = gameSpawn.getY();
- double z = gameSpawn.getZ();
- // Create the scatter locations based off the game's spawn
- List<Location> scatterLocations = new ArrayList<>(List.of(
- new Location(gameWorld, (x - 14.5), y, (z + 0.5), -90, 0),
- new Location(gameWorld, (x + 0.5), y, (z - 14.5), 0, 0),
- new Location(gameWorld, (x + 15.5), y, (z + 0.5), 90, 0),
- new Location(gameWorld, (x + 0.5), y, (z + 15.5), 180, 0),
- new Location(gameWorld, (x - 10.5), y, (z - 10.5), -45, 0),
- new Location(gameWorld, (x - 10.5), y, (z + 11.5), -135, 0),
- new Location(gameWorld, (x + 11.5), y, (z - 10.5), 45, 0),
- new Location(gameWorld, (x + 11.5), y, (z + 11.5), 135, 0)));
- // Shuffle the list (randomize)
- Collections.shuffle(scatterLocations);
- // While there are still unteleported players from the list, teleport them
- for (Player aPlayer : players) {
- // Select a singular player and singular location from the lists and teleport that player
- aPlayer.teleport(scatterLocations.get(0));
- // Remove that location so multiple players won't get the same one
- scatterLocations.remove(0);
- }
- }
-
- private void roundEnd(@Nullable Player winner) {
- // Cancel the tasks that auto-end the round
- Bukkit.getServer().getScheduler().cancelTask(gameID);
- // Clear old layers (as a fill command, this would be /fill ~-20 ~-20 ~-20 ~20 ~ ~20 relative to spawn)
- Generator.generateCuboid(new Location(gameSpawn.getWorld(), gameSpawn.getX() - 20, gameSpawn.getY() - 20, gameSpawn.getZ() - 20), new Location(gameSpawn.getWorld(), gameSpawn.getX() + 20, gameSpawn.getY(), gameSpawn.getZ() + 20), Material.AIR);
- playSound(gamePlayers, Sound.BLOCK_NOTE_BLOCK_PLING, SoundCategory.BLOCKS, 5, 0);
- // Check if there was a definite winner or not
- if (winner != null) {
- // Set the wins of the player to their current # of wins + 1
- gameWins.set(gamePlayers.indexOf(winner), (gameWins.get(gamePlayers.indexOf(winner)) + 1));
- // If the player has three wins, they won the game, so initiate the gameEnd
- if (gameWins.get(gamePlayers.indexOf(winner)) == 3) {
- gameEnd(winner);
- }
- // If that player doesn't have three wins, nobody else does, so we need another round
- else {
- roundPlayers.get(0).setGameMode(GameMode.SPECTATOR);
- roundPlayers.remove(0);
- roundPlayers.addAll(gamePlayers);
- clearInventories(gamePlayers);
- displayTitles(gamePlayers, ChatColor.RED + "Round over!", ChatColor.GOLD + winner.getName() + " has won the round!", 5, 60, 5);
- // Wait for player to respawn before completely l a g g i n g the server ._.
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- // Re-generate layers
- generateLayers(gameType);
- // Wait 5s (100t) for tp method
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- // Kill all items (pistons are weird)
- for (Entity entity : gameWorld.getEntities()) {
- if (entity instanceof Item) {
- entity.remove();
- }
- }
- // Re-scatter players
- gameState = "starting";
- scatterPlayers(gamePlayers);
- playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 5, 1);
- displayTitles(gamePlayers, ChatColor.DARK_GREEN + "3", null, 3, 10, 7);
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 5, 1);
- displayTitles(gamePlayers, ChatColor.YELLOW + "2", null, 3, 10, 7);
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 5, 1);
- displayTitles(gamePlayers, ChatColor.DARK_RED + "1", null, 3, 10, 7);
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 5, 2);
- displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1);
- setGamemode(gamePlayers, GameMode.SURVIVAL);
- gameState = "running";
- }, 20);
- }, 20);
- }, 20);
- }, 100);
- }, 1);
- }
- }
- else {
- setGamemode(gamePlayers, GameMode.SPECTATOR);
- roundPlayers.removeAll(roundPlayers);
- roundPlayers.addAll(gamePlayers);
- clearInventories(gamePlayers);
- displayTitles(gamePlayers, ChatColor.RED + "Round over!", ChatColor.GOLD + "Draw!", 5, 60, 5);
- // Wait for player to respawn before completely l a g g i n g the server ._.
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- // Re-generate layers
- generateLayers(gameType);
- // Wait 5s (100t) for tp method
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- // Kill all items (pistons are weird)
- for (Entity entity : gameWorld.getEntities()) {
- if (entity instanceof Item) {
- entity.remove();
- }
- }
- // Re-scatter players
- gameState = "starting";
- scatterPlayers(gamePlayers);
- playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 5, 1);
- displayTitles(gamePlayers, ChatColor.DARK_GREEN + "3", null, 3, 10, 7);
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 5, 1);
- displayTitles(gamePlayers, ChatColor.YELLOW + "2", null, 3, 10, 7);
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 5, 1);
- displayTitles(gamePlayers, ChatColor.DARK_RED + "1", null, 3, 10, 7);
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 5, 2);
- displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1);
- setGamemode(gamePlayers, GameMode.SURVIVAL);
- gameState = "running";
- }, 20);
- }, 20);
- }, 20);
- }, 100);
- }, 1);
- }
- }
-
- private void gameEnd(Player winner) {
- winner.setGameMode(GameMode.SPECTATOR);
- clearInventories(gamePlayers);
- // Announce win
- displayTitles(gamePlayers, ChatColor.RED + "Game over!", ChatColor.GOLD + winner.getName() + " has won the game!", 5, 60, 5);
- displayActionbar(gamePlayers, ChatColor.BLUE + "Returning to lobby in ten seconds...");
- // Wait 10s (200t), then
- Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> {
- // First, check to see if there is a separate location to tp the winner to
- if ((TumbleManager.getPlugin().getConfig().getDouble("winnerTeleport.x") != 0) && (TumbleManager.getPlugin().getConfig().getDouble("winnerTeleport.y") != 0) && (TumbleManager.getPlugin().getConfig().getDouble("winnerTeleport.z") != 0)) {
- // Tp the winner to that location
- winner.teleport(new Location(Bukkit.getWorld(TumbleManager.getLobbyWorld()), TumbleManager.getPlugin().getConfig().getDouble("winnerTeleport.x"), TumbleManager.getPlugin().getConfig().getDouble("winnerTeleport.y"), TumbleManager.getPlugin().getConfig().getDouble("winnerTeleport.z")));
- // Remove the winner from the gamePlayers so they don't get double-tp'd
- gamePlayers.remove(winner);
- }
- // Send all players back to lobby (spawn)
- for (Player aPlayer : gamePlayers) {
- aPlayer.teleport(Bukkit.getWorld(TumbleManager.getLobbyWorld()).getSpawnLocation());
- }
- }, 200);
- gameState = "complete";
- }
-}
diff --git a/src/main/java/com/MylesAndMore/tumble/Main.java b/src/main/java/com/MylesAndMore/tumble/Main.java
deleted file mode 100644
index 4dd4e25..0000000
--- a/src/main/java/com/MylesAndMore/tumble/Main.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.MylesAndMore.tumble;
-
-import com.MylesAndMore.tumble.commands.*;
-import com.MylesAndMore.tumble.api.Metrics;
-import org.bukkit.Bukkit;
-import org.bukkit.plugin.java.JavaPlugin;
-
-public class Main extends JavaPlugin{
- @Override
- public void onEnable() {
- // Register our event listener
- getServer().getPluginManager().registerEvents(new EventListener(), this);
- // Register commands
- this.getCommand("reload").setExecutor(new ReloadCommand());
- this.getCommand("link").setExecutor(new SetWorldConfig());
- this.getCommand("start").setExecutor(new StartGame());
- this.getCommand("winlocation").setExecutor(new SetWinnerLoc());
- this.getCommand("autostart").setExecutor(new SetAutoStart());
- // Save the default config file (packaged in the JAR)
- this.saveDefaultConfig();
-
- // Register bStats
- int pluginId = 16940;
- Metrics metrics = new Metrics(this, 16940);
-
- // Check if worlds are null in config
- if (TumbleManager.getGameWorld() == null) {
- Bukkit.getServer().getLogger().warning("[Tumble] It appears you have not configured a game world for Tumble.");
- Bukkit.getServer().getLogger().info("[Tumble] If this is your first time running the plugin, you may disregard this message.");
- }
- if (TumbleManager.getLobbyWorld() == null) {
- Bukkit.getServer().getLogger().warning("[Tumble] It appears you have not configured a lobby world for Tumble.");
- Bukkit.getServer().getLogger().info("[Tumble] If this is your first time running the plugin, you may disregard this message.");
- }
-
- // Init message
- Bukkit.getServer().getLogger().info("[Tumble] Tumble successfully enabled!");
- }
-} \ No newline at end of file
diff --git a/src/main/java/com/MylesAndMore/tumble/TumbleManager.java b/src/main/java/com/MylesAndMore/tumble/TumbleManager.java
deleted file mode 100644
index 43cc241..0000000
--- a/src/main/java/com/MylesAndMore/tumble/TumbleManager.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.MylesAndMore.tumble;
-
-import com.onarandombox.MultiverseCore.MultiverseCore;
-import com.onarandombox.MultiverseCore.api.MVWorldManager;
-import org.bukkit.Bukkit;
-import org.bukkit.entity.Player;
-import org.bukkit.plugin.Plugin;
-
-import java.util.List;
-
-/**
- * Class to store long return methods to make writing this plugin slightly less painful.
- */
-public class TumbleManager {
- // Tumble plugin
- public static Plugin getPlugin() {
- return Bukkit.getServer().getPluginManager().getPlugin("tumble");
- }
-
- // Tumble static methods
- public static String getPermissionMessage() { return TumbleManager.getPlugin().getConfig().getString("permissionMessage"); }
- public static String getGameWorld() { return TumbleManager.getPlugin().getConfig().getString("gameWorld"); }
- public static String getLobbyWorld() { return TumbleManager.getPlugin().getConfig().getString("lobbyWorld"); }
- public static String getGameType() { return TumbleManager.getPlugin().getConfig().getString("gameMode"); }
- public static List<Player> getPlayersInGame() { return Bukkit.getServer().getWorld(TumbleManager.getGameWorld()).getPlayers(); }
- public static List<Player> getPlayersInLobby() { return Bukkit.getServer().getWorld(TumbleManager.getLobbyWorld()).getPlayers(); }
-
-
- // Multiverse plugin
- public static MultiverseCore getMV() { return (MultiverseCore) Bukkit.getServer().getPluginManager().getPlugin("Multiverse-Core"); }
- // Multiverse worldManager
- public static MVWorldManager getMVWorldManager() { return getMV().getMVWorldManager(); }
-}
diff --git a/src/main/java/com/MylesAndMore/tumble/api/Generator.java b/src/main/java/com/MylesAndMore/tumble/api/Generator.java
deleted file mode 100644
index db8bacc..0000000
--- a/src/main/java/com/MylesAndMore/tumble/api/Generator.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package com.MylesAndMore.tumble.api;
-
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.World;
-import org.bukkit.block.Block;
-import org.bukkit.block.BlockFace;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Random;
-
-/**
- * This class holds the methods that generate blocks in-game such as cylinders, cubiods, and clump logic.
- */
-public class Generator {
- /**
- * Generates a layer (bascally just a cylinder) as best as it can w/ blocks
- *
- * @return A list of Blocks containing all the blocks it just changed
- *
- * @param center The center of the layer (Location)
- * @param radius The whole number radius of the circle
- * @param height The whole number height of the circle (1 for a flat layer)
- * @param material The Material to use for generation
- */
- public static List<Block> generateLayer(Location center, int radius, int height, Material material) {
- int Cx = center.getBlockX();
- int Cy = center.getBlockY();
- int Cz = center.getBlockZ();
- World world = center.getWorld();
- List<Block> blocks = new ArrayList<>();
-
- int rSq = radius * radius;
-
- for (int y = Cy; y < Cy + height; y++) {
- for (int x = Cx - radius; x <= Cx + radius; x++) {
- for (int z = Cz - radius; z <= Cz + radius; z++) {
- if ((Cx - x) * (Cx - x) + (Cz - z) * (Cz - z) <= rSq) {
- world.getBlockAt(x, y, z).setType(material);
- blocks.add(world.getBlockAt(x, y, z));
- }
- }
- }
- }
- return blocks;
- }
-
- /**
- * Generates a cubiod (literally just a ripoff fill command)
- * @param firstPos The first Location to fill (first three coords in a fill command)
- * @param secondPos The second Location to fill to (second three coords)
- * @param material The Material to fill
- */
- public static List<Block> generateCuboid(Location firstPos, Location secondPos, Material material) {
- World world = firstPos.getWorld();
- List<Block> blocks = new ArrayList<>();
- int fX = firstPos.getBlockX();
- int fY = firstPos.getBlockY();
- int fZ = firstPos.getBlockZ();
- int sX = secondPos.getBlockX();
- int sY = secondPos.getBlockY();
- int sZ = secondPos.getBlockZ();
-
- for (int x = fX; x <= sX; x++) {
- for (int y = fY; y <= sY; y++) {
- for (int z = fZ; z <= sZ; z++) {
- world.getBlockAt(x, y, z).setType(material);
- blocks.add(world.getBlockAt(x, y, z));
- }
- }
- }
- return blocks;
- }
-
- /**
- * Generates clumps in a pre-generated layer.
- * @param blockList A list of block Locations that this method is allowed to edit
- * @param materialList A list of Materials for the generator to randomly choose from.
- * Keep in mind that not all Materials may be used, the amount used depends on the size of the layer.
- * More Materials = more randomization
- */
- public static void generateClumps(List<Block> blockList, List<Material> materialList) {
- // Define random class
- Random random = new Random();
- // Define new blocks list so we can manipulate it
- List<Block> blocks = new ArrayList<>(blockList);
- // Define new shuffled Materials list
- List<Material> materials = new ArrayList<>(materialList);
- Collections.shuffle(materials);
- // This loop will run until there are no blocks left to change
- while (blocks.size() > 0) {
- // Get a random Material from the provided materials list
- Material randomMaterial = materials.get(random.nextInt(materials.size()));
- // Gets the first Block from the list, to modify
- Block aBlock = blocks.get(0);
- // Modifies the block
- aBlock.setType(randomMaterial);
- // Get the blocks around that and change it to that same material
- if (blocks.contains(aBlock.getRelative(BlockFace.NORTH))) {
- aBlock.getRelative(BlockFace.NORTH).setType(randomMaterial);
- blocks.remove(aBlock.getRelative(BlockFace.NORTH));
- }
- if (blocks.contains(aBlock.getRelative(BlockFace.SOUTH))) {
- aBlock.getRelative(BlockFace.SOUTH).setType(randomMaterial);
- blocks.remove(aBlock.getRelative(BlockFace.SOUTH));
- }
- if (blocks.contains(aBlock.getRelative(BlockFace.EAST))) {
- aBlock.getRelative(BlockFace.EAST).setType(randomMaterial);
- blocks.remove(aBlock.getRelative(BlockFace.EAST));
- }
- if (blocks.contains(aBlock.getRelative(BlockFace.WEST))) {
- aBlock.getRelative(BlockFace.WEST).setType(randomMaterial);
- blocks.remove(aBlock.getRelative(BlockFace.WEST));
- }
- blocks.remove(aBlock);
- }
- }
-}
diff --git a/src/main/java/com/MylesAndMore/tumble/api/Layers.java b/src/main/java/com/MylesAndMore/tumble/api/Layers.java
deleted file mode 100644
index d0d5890..0000000
--- a/src/main/java/com/MylesAndMore/tumble/api/Layers.java
+++ /dev/null
@@ -1,373 +0,0 @@
-package com.MylesAndMore.tumble.api;
-
-import org.bukkit.Material;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-
-/**
- * This class is dedicated to storing the different types of layers that can be generated.
- */
-public class Layers {
-
- public Layers(){
- matList.add(gen0);
- matList.add(gen1);
- matList.add(gen2);
- matList.add(gen3);
- matList.add(gen4);
- matList.add(gen5);
- matList.add(gen6);
- matList.add(gen7);
- matList.add(gen8);
- matList.add(gen9);
- matList.add(gen10);
- matList.add(gen12);
- matList.add(gen14);
- matList.add(gen15);
- matList.add(gen16);
- matList.add(gen0);
- matList.add(gen1);
- matList.add(gen2);
- matList.add(gen3);
- matList.add(gen4);
- matList.add(gen5);
- matList.add(gen6);
- matList.add(gen7);
- matList.add(gen8);
- matList.add(gen9);
- matList.add(gen10);
- matList.add(gen12);
- matList.add(gen14);
- matList.add(gen15);
- matList.add(gen16);
- matList.add(gen0);
- matList.add(gen1);
- matList.add(gen2);
- matList.add(gen3);
- matList.add(gen4);
- matList.add(gen5);
- matList.add(gen6);
- matList.add(gen7);
- matList.add(gen8);
- matList.add(gen9);
- matList.add(gen10);
- matList.add(gen12);
- matList.add(gen14);
- matList.add(gen15);
- matList.add(gen16);
- // Troll glass layer
- matList.add(gen11);
-
- safeMatList.add(gen1);
- safeMatList.add(gen2);
- safeMatList.add(gen4);
- safeMatList.add(gen5);
- safeMatList.add(gen7);
- safeMatList.add(gen9);
- safeMatList.add(gen10);
- safeMatList.add(gen1);
- safeMatList.add(gen2);
- safeMatList.add(gen4);
- safeMatList.add(gen5);
- safeMatList.add(gen7);
- safeMatList.add(gen9);
- safeMatList.add(gen10);
- safeMatList.add(gen1);
- safeMatList.add(gen2);
- safeMatList.add(gen4);
- safeMatList.add(gen5);
- safeMatList.add(gen7);
- safeMatList.add(gen9);
- safeMatList.add(gen10);
- // Troll glass layer
- safeMatList.add(gen11);
- }
-
- // Define Random class
- Random random = new Random();
- /**
- * @return A random predefined List of Materials that are okay to use in the clump generator
- */
- public List<Material> getMaterialList() {
- return matList.get(random.nextInt(matList.size()));
- }
-
- /**
- * @return A random predefined List of Materials that are okay to spawn players on top of
- */
- public List<Material> getSafeMaterialList() { return safeMatList.get(random.nextInt(safeMatList.size())); }
-
- // Begin lists
-
- // private final List<Material> gen = new ArrayList<>() {{
- // add(Material.
- // }};
-
- private final List<Material> gen0 = new ArrayList<>() {{
- add(Material.COAL_ORE);
- add(Material.COAL_ORE);
- add(Material.COAL_ORE);
- add(Material.COAL_ORE);
- add(Material.COAL_ORE);
- add(Material.IRON_ORE);
- add(Material.REDSTONE_ORE);
- add(Material.EMERALD_ORE);
- add(Material.GOLD_ORE);
- add(Material.LAPIS_ORE);
- add(Material.DIAMOND_ORE);
- add(Material.GRASS_BLOCK);
- add(Material.GRASS_BLOCK);
- add(Material.GRASS_BLOCK);
- add(Material.GRASS_BLOCK);
- add(Material.COBWEB);
- }};
-
- private final List<Material> gen1 = new ArrayList<>() {{
- add(Material.YELLOW_GLAZED_TERRACOTTA);
- add(Material.LIGHT_BLUE_GLAZED_TERRACOTTA);
- add(Material.GRAY_GLAZED_TERRACOTTA);
- add(Material.PODZOL);
- add(Material.PODZOL);
- add(Material.PODZOL);
- add(Material.ORANGE_GLAZED_TERRACOTTA);
- }};
-
- private final List<Material> gen2 = new ArrayList<>() {{
- add(Material.PINK_TERRACOTTA);
- add(Material.PURPLE_TERRACOTTA);
- add(Material.GRAY_TERRACOTTA);
- add(Material.BLUE_TERRACOTTA);
- add(Material.LIGHT_BLUE_TERRACOTTA);
- add(Material.WHITE_TERRACOTTA);
- add(Material.BROWN_TERRACOTTA);
- add(Material.GREEN_TERRACOTTA);
- add(Material.YELLOW_TERRACOTTA);
- add(Material.PINK_TERRACOTTA);
- add(Material.PURPLE_TERRACOTTA);
- add(Material.GRAY_TERRACOTTA);
- add(Material.BLUE_TERRACOTTA);
- add(Material.LIGHT_BLUE_TERRACOTTA);
- add(Material.WHITE_TERRACOTTA);
- add(Material.BROWN_TERRACOTTA);
- add(Material.GREEN_TERRACOTTA);
- add(Material.YELLOW_TERRACOTTA);
- add(Material.WHITE_STAINED_GLASS);
- add(Material.HONEYCOMB_BLOCK);
- add(Material.HONEYCOMB_BLOCK);
- }};
-
- private final List<Material> gen3 = new ArrayList<>() {{
- add(Material.PACKED_ICE);
- add(Material.PACKED_ICE);
- add(Material.NOTE_BLOCK);
- add(Material.TNT);
- add(Material.LIGHT_BLUE_CONCRETE);
- add(Material.GLASS);
- add(Material.PACKED_ICE);
- add(Material.PACKED_ICE);
- add(Material.NOTE_BLOCK);
- add(Material.TNT);
- add(Material.LIGHT_BLUE_CONCRETE);
- add(Material.GLASS);
- add(Material.SOUL_SAND);
- }};
-
- private final List<Material> gen4 = new ArrayList<>() {{
- add(Material.DIAMOND_BLOCK);
- add(Material.GOLD_BLOCK);
- add(Material.REDSTONE_BLOCK);
- add(Material.REDSTONE_BLOCK);
- add(Material.LAPIS_BLOCK);
- add(Material.LAPIS_BLOCK);
- add(Material.IRON_BLOCK);
- add(Material.COAL_BLOCK);
- add(Material.IRON_BLOCK);
- add(Material.COAL_BLOCK);
- add(Material.IRON_BLOCK);
- add(Material.COAL_BLOCK);
- add(Material.COAL_BLOCK);
- }};
-
- private final List<Material> gen5 = new ArrayList<>() {{
- add(Material.WHITE_TERRACOTTA);
- add(Material.BLUE_ICE);
- add(Material.SOUL_SAND);
- add(Material.STONE_SLAB);
- add(Material.WHITE_TERRACOTTA);
- add(Material.BLUE_ICE);
- add(Material.SOUL_SAND);
- add(Material.STONE_SLAB);
- add(Material.WHITE_TERRACOTTA);
- add(Material.BLUE_ICE);
- add(Material.SOUL_SAND);
- add(Material.STONE_SLAB);
- add(Material.GLOWSTONE);
- add(Material.GLOWSTONE);
- add(Material.HONEY_BLOCK);
- add(Material.SLIME_BLOCK);
- }};
-
- private final List<Material> gen6 = new ArrayList<>() {{
- add(Material.NETHERRACK);
- add(Material.NETHERRACK);
- add(Material.NETHERRACK);
- add(Material.NETHER_BRICKS);
- add(Material.NETHER_BRICKS);
- add(Material.NETHERRACK);
- add(Material.NETHERRACK);
- add(Material.NETHERRACK);
- add(Material.NETHER_BRICKS);
- add(Material.NETHER_BRICKS);
- add(Material.NETHER_GOLD_ORE);
- add(Material.NETHER_GOLD_ORE);
- add(Material.CRIMSON_NYLIUM);
- add(Material.WARPED_NYLIUM);
- add(Material.SOUL_SOIL);
- add(Material.CRACKED_NETHER_BRICKS);
- add(Material.RED_NETHER_BRICKS);
- add(Material.NETHER_WART_BLOCK);
- add(Material.CRYING_OBSIDIAN);
- add(Material.MAGMA_BLOCK);
- }};
-
- private final List<Material> gen7 = new ArrayList<>() {{
- add(Material.END_STONE);
- add(Material.END_STONE_BRICKS);
- add(Material.END_STONE);
- add(Material.END_STONE_BRICKS);
- add(Material.END_STONE);
- add(Material.END_STONE_BRICKS);
- add(Material.END_STONE);
- add(Material.END_STONE_BRICKS);
- add(Material.OBSIDIAN);
- add(Material.PURPUR_BLOCK);
- add(Material.PURPUR_PILLAR);
- add(Material.COBBLESTONE);
- }};
-
- private final List<Material> gen8 = new ArrayList<>() {{
- add(Material.REDSTONE_BLOCK);
- add(Material.REDSTONE_BLOCK);
- add(Material.REDSTONE_LAMP);
- add(Material.TARGET);
- add(Material.DAYLIGHT_DETECTOR);
- add(Material.PISTON);
- add(Material.STICKY_PISTON);
- add(Material.SLIME_BLOCK);
- add(Material.OBSERVER);
- add(Material.HOPPER);
- }};
-
- private final List<Material> gen9 = new ArrayList<>() {{
- add(Material.PRISMARINE);
- add(Material.DARK_PRISMARINE);
- add(Material.BLUE_STAINED_GLASS);
- add(Material.WET_SPONGE);
- add(Material.PRISMARINE_BRICKS);
- add(Material.PRISMARINE_BRICK_SLAB);
- add(Material.DARK_PRISMARINE);
- add(Material.SEA_LANTERN);
- add(Material.TUBE_CORAL_BLOCK);
- add(Material.BRAIN_CORAL_BLOCK);
- add(Material.BUBBLE_CORAL_BLOCK);
- }};
-
- private final List<Material> gen10 = new ArrayList<>() {{
- add(Material.OAK_LOG);
- add(Material.SPRUCE_LOG);
- add(Material.ACACIA_LOG);
- add(Material.STRIPPED_OAK_LOG);
- add(Material.STRIPPED_SPRUCE_LOG);
- add(Material.STRIPPED_ACACIA_LOG);
- add(Material.OAK_WOOD);
- add(Material.SPRUCE_WOOD);
- add(Material.ACACIA_WOOD);
- add(Material.OAK_LEAVES);
- add(Material.SPRUCE_LEAVES);
- add(Material.ACACIA_LEAVES);
- add(Material.OAK_LEAVES);
- add(Material.SPRUCE_LEAVES);
- add(Material.ACACIA_LEAVES);
- }};
-
- private final List<Material> gen11 = new ArrayList<>() {{
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.GLASS);
- add(Material.WHITE_STAINED_GLASS);
- }};
-
- private final List<Material> gen12 = new ArrayList<>() {{
- add(Material.DIRT);
- add(Material.DIRT_PATH);
- add(Material.GRASS_BLOCK);
- add(Material.OAK_SLAB);
- add(Material.BRICK_WALL);
- add(Material.BRICK_STAIRS);
- }};
-
- private final List<Material> gen14 = new ArrayList<>() {{
- add(Material.LECTERN);
- add(Material.OBSIDIAN);
- add(Material.SPONGE);
- add(Material.BEEHIVE);
- add(Material.DRIED_KELP_BLOCK);
- }};
-
- private final List<Material> gen15 = new ArrayList<>() {{
- add(Material.SANDSTONE);
- add(Material.SANDSTONE_SLAB);
- add(Material.RED_SANDSTONE);
- add(Material.RED_SANDSTONE_SLAB);
- add(Material.RED_TERRACOTTA);
- add(Material.TERRACOTTA);
- add(Material.YELLOW_TERRACOTTA);
- }};
-
- private final List<Material> gen16 = new ArrayList<>() {{
- add(Material.JUNGLE_LOG);
- add(Material.STRIPPED_JUNGLE_LOG);
- add(Material.JUNGLE_WOOD);
- add(Material.STRIPPED_JUNGLE_WOOD);
- add(Material.MOSSY_COBBLESTONE);
- add(Material.MOSSY_COBBLESTONE);
- add(Material.MOSSY_COBBLESTONE);
- add(Material.JUNGLE_LEAVES);
- add(Material.JUNGLE_SLAB);
- add(Material.JUNGLE_TRAPDOOR);
- }};
-
- private final List<List<Material>> matList = new ArrayList<>();
-
- private final List<List<Material>> safeMatList = new ArrayList<>();
-
-}
diff --git a/src/main/java/com/MylesAndMore/tumble/api/Metrics.java b/src/main/java/com/MylesAndMore/tumble/api/Metrics.java
deleted file mode 100644
index 411a918..0000000
--- a/src/main/java/com/MylesAndMore/tumble/api/Metrics.java
+++ /dev/null
@@ -1,865 +0,0 @@
-// Do NOT remove this file! The build will fail--it is to enable bStats.
-
-/*
- * This Metrics class was auto-generated and can be copied into your project if you are
- * not using a build tool like Gradle or Maven for dependency management.
- *
- * IMPORTANT: You are not allowed to modify this class, except changing the package.
- *
- * Unallowed modifications include but are not limited to:
- * - Remove the option for users to opt-out
- * - Change the frequency for data submission
- * - Obfuscate the code (every obfucator should allow you to make an exception for specific files)
- * - Reformat the code (if you use a linter, add an exception)
- *
- * Violations will result in a ban of your plugin and account from bStats.
- */
-package com.MylesAndMore.tumble.api;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
-import java.util.logging.Level;
-import java.util.stream.Collectors;
-import java.util.zip.GZIPOutputStream;
-import javax.net.ssl.HttpsURLConnection;
-import org.bukkit.Bukkit;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.bukkit.entity.Player;
-import org.bukkit.plugin.Plugin;
-import org.bukkit.plugin.java.JavaPlugin;
-
-public class Metrics {
-
- private final Plugin plugin;
-
- private final MetricsBase metricsBase;
-
- /**
- * Creates a new Metrics instance.
- *
- * @param plugin Your plugin instance.
- * @param serviceId The id of the service. It can be found at <a
- * href="https://bstats.org/what-is-my-plugin-id">What is my plugin id?</a>
- */
- public Metrics(JavaPlugin plugin, int serviceId) {
- this.plugin = plugin;
- // Get the config file
- File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
- File configFile = new File(bStatsFolder, "config.yml");
- YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
- if (!config.isSet("serverUuid")) {
- config.addDefault("enabled", true);
- config.addDefault("serverUuid", UUID.randomUUID().toString());
- config.addDefault("logFailedRequests", false);
- config.addDefault("logSentData", false);
- config.addDefault("logResponseStatusText", false);
- // Inform the server owners about bStats
- config
- .options()
- .header(
- "bStats (https://bStats.org) collects some basic information for plugin authors, like how\n"
- + "many people use their plugin and their total player count. It's recommended to keep bStats\n"
- + "enabled, but if you're not comfortable with this, you can turn this setting off. There is no\n"
- + "performance penalty associated with having metrics enabled, and data sent to bStats is fully\n"
- + "anonymous.")
- .copyDefaults(true);
- try {
- config.save(configFile);
- } catch (IOException ignored) {
- }
- }
- // Load the data
- boolean enabled = config.getBoolean("enabled", true);
- String serverUUID = config.getString("serverUuid");
- boolean logErrors = config.getBoolean("logFailedRequests", false);
- boolean logSentData = config.getBoolean("logSentData", false);
- boolean logResponseStatusText = config.getBoolean("logResponseStatusText", false);
- metricsBase =
- new MetricsBase(
- "bukkit",
- serverUUID,
- serviceId,
- enabled,
- this::appendPlatformData,
- this::appendServiceData,
- submitDataTask -> Bukkit.getScheduler().runTask(plugin, submitDataTask),
- plugin::isEnabled,
- (message, error) -> this.plugin.getLogger().log(Level.WARNING, message, error),
- (message) -> this.plugin.getLogger().log(Level.INFO, message),
- logErrors,
- logSentData,
- logResponseStatusText);
- }
-
- /**
- * Adds a custom chart.
- *
- * @param chart The chart to add.
- */
- public void addCustomChart(CustomChart chart) {
- metricsBase.addCustomChart(chart);
- }
-
- private void appendPlatformData(JsonObjectBuilder builder) {
- builder.appendField("playerAmount", getPlayerAmount());
- builder.appendField("onlineMode", Bukkit.getOnlineMode() ? 1 : 0);
- builder.appendField("bukkitVersion", Bukkit.getVersion());
- builder.appendField("bukkitName", Bukkit.getName());
- builder.appendField("javaVersion", System.getProperty("java.version"));
- builder.appendField("osName", System.getProperty("os.name"));
- builder.appendField("osArch", System.getProperty("os.arch"));
- builder.appendField("osVersion", System.getProperty("os.version"));
- builder.appendField("coreCount", Runtime.getRuntime().availableProcessors());
- }
-
- private void appendServiceData(JsonObjectBuilder builder) {
- builder.appendField("pluginVersion", plugin.getDescription().getVersion());
- }
-
- private int getPlayerAmount() {
- try {
- // Around MC 1.8 the return type was changed from an array to a collection,
- // This fixes java.lang.NoSuchMethodError:
- // org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection;
- Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers");
- return onlinePlayersMethod.getReturnType().equals(Collection.class)
- ? ((Collection<?>) onlinePlayersMethod.invoke(Bukkit.getServer())).size()
- : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length;
- } catch (Exception e) {
- // Just use the new method if the reflection failed
- return Bukkit.getOnlinePlayers().size();
- }
- }
-
- public static class MetricsBase {
-
- /** The version of the Metrics class. */
- public static final String METRICS_VERSION = "3.0.0";
-
- private static final ScheduledExecutorService scheduler =
- Executors.newScheduledThreadPool(1, task -> new Thread(task, "bStats-Metrics"));
-
- private static final String REPORT_URL = "https://bStats.org/api/v2/data/%s";
-
- private final String platform;
-
- private final String serverUuid;
-
- private final int serviceId;
-
- private final Consumer<JsonObjectBuilder> appendPlatformDataConsumer;
-
- private final Consumer<JsonObjectBuilder> appendServiceDataConsumer;
-
- private final Consumer<Runnable> submitTaskConsumer;
-
- private final Supplier<Boolean> checkServiceEnabledSupplier;
-
- private final BiConsumer<String, Throwable> errorLogger;
-
- private final Consumer<String> infoLogger;
-
- private final boolean logErrors;
-
- private final boolean logSentData;
-
- private final boolean logResponseStatusText;
-
- private final Set<CustomChart> customCharts = new HashSet<>();
-
- private final boolean enabled;
-
- /**
- * Creates a new MetricsBase class instance.
- *
- * @param platform The platform of the service.
- * @param serviceId The id of the service.
- * @param serverUuid The server uuid.
- * @param enabled Whether or not data sending is enabled.
- * @param appendPlatformDataConsumer A consumer that receives a {@code JsonObjectBuilder} and
- * appends all platform-specific data.
- * @param appendServiceDataConsumer A consumer that receives a {@code JsonObjectBuilder} and
- * appends all service-specific data.
- * @param submitTaskConsumer A consumer that takes a runnable with the submit task. This can be
- * used to delegate the data collection to a another thread to prevent errors caused by
- * concurrency. Can be {@code null}.
- * @param checkServiceEnabledSupplier A supplier to check if the service is still enabled.
- * @param errorLogger A consumer that accepts log message and an error.
- * @param infoLogger A consumer that accepts info log messages.
- * @param logErrors Whether or not errors should be logged.
- * @param logSentData Whether or not the sent data should be logged.
- * @param logResponseStatusText Whether or not the response status text should be logged.
- */
- public MetricsBase(
- String platform,
- String serverUuid,
- int serviceId,
- boolean enabled,
- Consumer<JsonObjectBuilder> appendPlatformDataConsumer,
- Consumer<JsonObjectBuilder> appendServiceDataConsumer,
- Consumer<Runnable> submitTaskConsumer,
- Supplier<Boolean> checkServiceEnabledSupplier,
- BiConsumer<String, Throwable> errorLogger,
- Consumer<String> infoLogger,
- boolean logErrors,
- boolean logSentData,
- boolean logResponseStatusText) {
- this.platform = platform;
- this.serverUuid = serverUuid;
- this.serviceId = serviceId;
- this.enabled = enabled;
- this.appendPlatformDataConsumer = appendPlatformDataConsumer;
- this.appendServiceDataConsumer = appendServiceDataConsumer;
- this.submitTaskConsumer = submitTaskConsumer;
- this.checkServiceEnabledSupplier = checkServiceEnabledSupplier;
- this.errorLogger = errorLogger;
- this.infoLogger = infoLogger;
- this.logErrors = logErrors;
- this.logSentData = logSentData;
- this.logResponseStatusText = logResponseStatusText;
- checkRelocation();
- if (enabled) {
- // WARNING: Removing the option to opt-out will get your plugin banned from bStats
- startSubmitting();
- }
- }
-
- public void addCustomChart(CustomChart chart) {
- this.customCharts.add(chart);
- }
-
- private void startSubmitting() {
- final Runnable submitTask =
- () -> {
- if (!enabled || !checkServiceEnabledSupplier.get()) {
- // Submitting data or service is disabled
- scheduler.shutdown();
- return;
- }
- if (submitTaskConsumer != null) {
- submitTaskConsumer.accept(this::submitData);
- } else {
- this.submitData();
- }
- };
- // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution
- // of requests on the
- // bStats backend. To circumvent this problem, we introduce some randomness into the initial
- // and second delay.
- // WARNING: You must not modify and part of this Metrics class, including the submit delay or
- // frequency!
- // WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it!
- long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3));
- long secondDelay = (long) (1000 * 60 * (Math.random() * 30));
- scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS);
- scheduler.scheduleAtFixedRate(
- submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS);
- }
-
- private void submitData() {
- final JsonObjectBuilder baseJsonBuilder = new JsonObjectBuilder();
- appendPlatformDataConsumer.accept(baseJsonBuilder);
- final JsonObjectBuilder serviceJsonBuilder = new JsonObjectBuilder();
- appendServiceDataConsumer.accept(serviceJsonBuilder);
- JsonObjectBuilder.JsonObject[] chartData =
- customCharts.stream()
- .map(customChart -> customChart.getRequestJsonObject(errorLogger, logErrors))
- .filter(Objects::nonNull)
- .toArray(JsonObjectBuilder.JsonObject[]::new);
- serviceJsonBuilder.appendField("id", serviceId);
- serviceJsonBuilder.appendField("customCharts", chartData);
- baseJsonBuilder.appendField("service", serviceJsonBuilder.build());
- baseJsonBuilder.appendField("serverUUID", serverUuid);
- baseJsonBuilder.appendField("metricsVersion", METRICS_VERSION);
- JsonObjectBuilder.JsonObject data = baseJsonBuilder.build();
- scheduler.execute(
- () -> {
- try {
- // Send the data
- sendData(data);
- } catch (Exception e) {
- // Something went wrong! :(
- if (logErrors) {
- errorLogger.accept("Could not submit bStats metrics data", e);
- }
- }
- });
- }
-
- private void sendData(JsonObjectBuilder.JsonObject data) throws Exception {
- if (logSentData) {
- infoLogger.accept("Sent bStats metrics data: " + data.toString());
- }
- String url = String.format(REPORT_URL, platform);
- HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection();
- // Compress the data to save bandwidth
- byte[] compressedData = compress(data.toString());
- connection.setRequestMethod("POST");
- connection.addRequestProperty("Accept", "application/json");
- connection.addRequestProperty("Connection", "close");
- connection.addRequestProperty("Content-Encoding", "gzip");
- connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
- connection.setRequestProperty("Content-Type", "application/json");
- connection.setRequestProperty("User-Agent", "Metrics-Service/1");
- connection.setDoOutput(true);
- try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
- outputStream.write(compressedData);
- }
- StringBuilder builder = new StringBuilder();
- try (BufferedReader bufferedReader =
- new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
- String line;
- while ((line = bufferedReader.readLine()) != null) {
- builder.append(line);
- }
- }
- if (logResponseStatusText) {
- infoLogger.accept("Sent data to bStats and received response: " + builder);
- }
- }
-
- /** Checks that the class was properly relocated. */
- private void checkRelocation() {
- // You can use the property to disable the check in your test environment
- if (System.getProperty("bstats.relocatecheck") == null
- || !System.getProperty("bstats.relocatecheck").equals("false")) {
- // Maven's Relocate is clever and changes strings, too. So we have to use this little
- // "trick" ... :D
- final String defaultPackage =
- new String(new byte[] {'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's'});
- final String examplePackage =
- new String(new byte[] {'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
- // We want to make sure no one just copy & pastes the example and uses the wrong package
- // names
- if (MetricsBase.class.getPackage().getName().startsWith(defaultPackage)
- || MetricsBase.class.getPackage().getName().startsWith(examplePackage)) {
- throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
- }
- }
- }
-
- /**
- * Gzips the given string.
- *
- * @param str The string to gzip.
- * @return The gzipped string.
- */
- private static byte[] compress(final String str) throws IOException {
- if (str == null) {
- return null;
- }
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) {
- gzip.write(str.getBytes(StandardCharsets.UTF_8));
- }
- return outputStream.toByteArray();
- }
- }
-
- public static class DrilldownPie extends CustomChart {
-
- private final Callable<Map<String, Map<String, Integer>>> callable;
-
- /**
- * Class constructor.
- *
- * @param chartId The id of the chart.
- * @param callable The callable which is used to request the chart data.
- */
- public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
- super(chartId);
- this.callable = callable;
- }
-
- @Override
- public JsonObjectBuilder.JsonObject getChartData() throws Exception {
- JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
- Map<String, Map<String, Integer>> map = callable.call();
- if (map == null || map.isEmpty()) {
- // Null = skip the chart
- return null;
- }
- boolean reallyAllSkipped = true;
- for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
- JsonObjectBuilder valueBuilder = new JsonObjectBuilder();
- boolean allSkipped = true;
- for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
- valueBuilder.appendField(valueEntry.getKey(), valueEntry.getValue());
- allSkipped = false;
- }
- if (!allSkipped) {
- reallyAllSkipped = false;
- valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build());
- }
- }
- if (reallyAllSkipped) {
- // Null = skip the chart
- return null;
- }
- return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
- }
- }
-
- public static class AdvancedPie extends CustomChart {
-
- private final Callable<Map<String, Integer>> callable;
-
- /**
- * Class constructor.
- *
- * @param chartId The id of the chart.
- * @param callable The callable which is used to request the chart data.
- */
- public AdvancedPie(String chartId, Callable<Map<String, Integer>> callable) {
- super(chartId);
- this.callable = callable;
- }
-
- @Override
- protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
- JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
- Map<String, Integer> map = callable.call();
- if (map == null || map.isEmpty()) {
- // Null = skip the chart
- return null;
- }
- boolean allSkipped = true;
- for (Map.Entry<String, Integer> entry : map.entrySet()) {
- if (entry.getValue() == 0) {
- // Skip this invalid
- continue;
- }
- allSkipped = false;
- valuesBuilder.appendField(entry.getKey(), entry.getValue());
- }
- if (allSkipped) {
- // Null = skip the chart
- return null;
- }
- return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
- }
- }
-
- public static class MultiLineChart extends CustomChart {
-
- private final Callable<Map<String, Integer>> callable;
-
- /**
- * Class constructor.
- *
- * @param chartId The id of the chart.
- * @param callable The callable which is used to request the chart data.
- */
- public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable) {
- super(chartId);
- this.callable = callable;
- }
-
- @Override
- protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
- JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
- Map<String, Integer> map = callable.call();
- if (map == null || map.isEmpty()) {
- // Null = skip the chart
- return null;
- }
- boolean allSkipped = true;
- for (Map.Entry<String, Integer> entry : map.entrySet()) {
- if (entry.getValue() == 0) {
- // Skip this invalid
- continue;
- }
- allSkipped = false;
- valuesBuilder.appendField(entry.getKey(), entry.getValue());
- }
- if (allSkipped) {
- // Null = skip the chart
- return null;
- }
- return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
- }
- }
-
- public static class SimpleBarChart extends CustomChart {
-
- private final Callable<Map<String, Integer>> callable;
-
- /**
- * Class constructor.
- *
- * @param chartId The id of the chart.
- * @param callable The callable which is used to request the chart data.
- */
- public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
- super(chartId);
- this.callable = callable;
- }
-
- @Override
- protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
- JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
- Map<String, Integer> map = callable.call();
- if (map == null || map.isEmpty()) {
- // Null = skip the chart
- return null;
- }
- for (Map.Entry<String, Integer> entry : map.entrySet()) {
- valuesBuilder.appendField(entry.getKey(), new int[] {entry.getValue()});
- }
- return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
- }
- }
-
- public abstract static class CustomChart {
-
- private final String chartId;
-
- protected CustomChart(String chartId) {
- if (chartId == null) {
- throw new IllegalArgumentException("chartId must not be null");
- }
- this.chartId = chartId;
- }
-
- public JsonObjectBuilder.JsonObject getRequestJsonObject(
- BiConsumer<String, Throwable> errorLogger, boolean logErrors) {
- JsonObjectBuilder builder = new JsonObjectBuilder();
- builder.appendField("chartId", chartId);
- try {
- JsonObjectBuilder.JsonObject data = getChartData();
- if (data == null) {
- // If the data is null we don't send the chart.
- return null;
- }
- builder.appendField("data", data);
- } catch (Throwable t) {
- if (logErrors) {
- errorLogger.accept("Failed to get data for custom chart with id " + chartId, t);
- }
- return null;
- }
- return builder.build();
- }
-
- protected abstract JsonObjectBuilder.JsonObject getChartData() throws Exception;
- }
-
- public static class SimplePie extends CustomChart {
-
- private final Callable<String> callable;
-
- /**
- * Class constructor.
- *
- * @param chartId The id of the chart.
- * @param callable The callable which is used to request the chart data.
- */
- public SimplePie(String chartId, Callable<String> callable) {
- super(chartId);
- this.callable = callable;
- }
-
- @Override
- protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
- String value = callable.call();
- if (value == null || value.isEmpty()) {
- // Null = skip the chart
- return null;
- }
- return new JsonObjectBuilder().appendField("value", value).build();
- }
- }
-
- public static class AdvancedBarChart extends CustomChart {
-
- private final Callable<Map<String, int[]>> callable;
-
- /**
- * Class constructor.
- *
- * @param chartId The id of the chart.
- * @param callable The callable which is used to request the chart data.
- */
- public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
- super(chartId);
- this.callable = callable;
- }
-
- @Override
- protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
- JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
- Map<String, int[]> map = callable.call();
- if (map == null || map.isEmpty()) {
- // Null = skip the chart
- return null;
- }
- boolean allSkipped = true;
- for (Map.Entry<String, int[]> entry : map.entrySet()) {
- if (entry.getValue().length == 0) {
- // Skip this invalid
- continue;
- }
- allSkipped = false;
- valuesBuilder.appendField(entry.getKey(), entry.getValue());
- }
- if (allSkipped) {
- // Null = skip the chart
- return null;
- }
- return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
- }
- }
-
- public static class SingleLineChart extends CustomChart {
-
- private final Callable<Integer> callable;
-
- /**
- * Class constructor.
- *
- * @param chartId The id of the chart.
- * @param callable The callable which is used to request the chart data.
- */
- public SingleLineChart(String chartId, Callable<Integer> callable) {
- super(chartId);
- this.callable = callable;
- }
-
- @Override
- protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
- int value = callable.call();
- if (value == 0) {
- // Null = skip the chart
- return null;
- }
- return new JsonObjectBuilder().appendField("value", value).build();
- }
- }
-
- /**
- * An extremely simple JSON builder.
- *
- * <p>While this class is neither feature-rich nor the most performant one, it's sufficient enough
- * for its use-case.
- */
- public static class JsonObjectBuilder {
-
- private StringBuilder builder = new StringBuilder();
-
- private boolean hasAtLeastOneField = false;
-
- public JsonObjectBuilder() {
- builder.append("{");
- }
-
- /**
- * Appends a null field to the JSON.
- *
- * @param key The key of the field.
- * @return A reference to this object.
- */
- public JsonObjectBuilder appendNull(String key) {
- appendFieldUnescaped(key, "null");
- return this;
- }
-
- /**
- * Appends a string field to the JSON.
- *
- * @param key The key of the field.
- * @param value The value of the field.
- * @return A reference to this object.
- */
- public JsonObjectBuilder appendField(String key, String value) {
- if (value == null) {
- throw new IllegalArgumentException("JSON value must not be null");
- }
- appendFieldUnescaped(key, "\"" + escape(value) + "\"");
- return this;
- }
-
- /**
- * Appends an integer field to the JSON.
- *
- * @param key The key of the field.
- * @param value The value of the field.
- * @return A reference to this object.
- */
- public JsonObjectBuilder appendField(String key, int value) {
- appendFieldUnescaped(key, String.valueOf(value));
- return this;
- }
-
- /**
- * Appends an object to the JSON.
- *
- * @param key The key of the field.
- * @param object The object.
- * @return A reference to this object.
- */
- public JsonObjectBuilder appendField(String key, JsonObject object) {
- if (object == null) {
- throw new IllegalArgumentException("JSON object must not be null");
- }
- appendFieldUnescaped(key, object.toString());
- return this;
- }
-
- /**
- * Appends a string array to the JSON.
- *
- * @param key The key of the field.
- * @param values The string array.
- * @return A reference to this object.
- */
- public JsonObjectBuilder appendField(String key, String[] values) {
- if (values == null) {
- throw new IllegalArgumentException("JSON values must not be null");
- }
- String escapedValues =
- Arrays.stream(values)
- .map(value -> "\"" + escape(value) + "\"")
- .collect(Collectors.joining(","));
- appendFieldUnescaped(key, "[" + escapedValues + "]");
- return this;
- }
-
- /**
- * Appends an integer array to the JSON.
- *
- * @param key The key of the field.
- * @param values The integer array.
- * @return A reference to this object.
- */
- public JsonObjectBuilder appendField(String key, int[] values) {
- if (values == null) {
- throw new IllegalArgumentException("JSON values must not be null");
- }
- String escapedValues =
- Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(","));
- appendFieldUnescaped(key, "[" + escapedValues + "]");
- return this;
- }
-
- /**
- * Appends an object array to the JSON.
- *
- * @param key The key of the field.
- * @param values The integer array.
- * @return A reference to this object.
- */
- public JsonObjectBuilder appendField(String key, JsonObject[] values) {
- if (values == null) {
- throw new IllegalArgumentException("JSON values must not be null");
- }
- String escapedValues =
- Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(","));
- appendFieldUnescaped(key, "[" + escapedValues + "]");
- return this;
- }
-
- /**
- * Appends a field to the object.
- *
- * @param key The key of the field.
- * @param escapedValue The escaped value of the field.
- */
- private void appendFieldUnescaped(String key, String escapedValue) {
- if (builder == null) {
- throw new IllegalStateException("JSON has already been built");
- }
- if (key == null) {
- throw new IllegalArgumentException("JSON key must not be null");
- }
- if (hasAtLeastOneField) {
- builder.append(",");
- }
- builder.append("\"").append(escape(key)).append("\":").append(escapedValue);
- hasAtLeastOneField = true;
- }
-
- /**
- * Builds the JSON string and invalidates this builder.
- *
- * @return The built JSON string.
- */
- public JsonObject build() {
- if (builder == null) {
- throw new IllegalStateException("JSON has already been built");
- }
- JsonObject object = new JsonObject(builder.append("}").toString());
- builder = null;
- return object;
- }
-
- /**
- * Escapes the given string like stated in https://www.ietf.org/rfc/rfc4627.txt.
- *
- * <p>This method escapes only the necessary characters '"', '\'. and '\u0000' - '\u001F'.
- * Compact escapes are not used (e.g., '\n' is escaped as "\u000a" and not as "\n").
- *
- * @param value The value to escape.
- * @return The escaped value.
- */
- private static String escape(String value) {
- final StringBuilder builder = new StringBuilder();
- for (int i = 0; i < value.length(); i++) {
- char c = value.charAt(i);
- if (c == '"') {
- builder.append("\\\"");
- } else if (c == '\\') {
- builder.append("\\\\");
- } else if (c <= '\u000F') {
- builder.append("\\u000").append(Integer.toHexString(c));
- } else if (c <= '\u001F') {
- builder.append("\\u00").append(Integer.toHexString(c));
- } else {
- builder.append(c);
- }
- }
- return builder.toString();
- }
-
- /**
- * A super simple representation of a JSON object.
- *
- * <p>This class only exists to make methods of the {@link JsonObjectBuilder} type-safe and not
- * allow a raw string inputs for methods like {@link JsonObjectBuilder#appendField(String,
- * JsonObject)}.
- */
- public static class JsonObject {
-
- private final String value;
-
- private JsonObject(String value) {
- this.value = value;
- }
-
- @Override
- public String toString() {
- return value;
- }
- }
- }
-}
diff --git a/src/main/java/com/MylesAndMore/tumble/commands/ReloadCommand.java b/src/main/java/com/MylesAndMore/tumble/commands/ReloadCommand.java
deleted file mode 100644
index 4ca26f4..0000000
--- a/src/main/java/com/MylesAndMore/tumble/commands/ReloadCommand.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.MylesAndMore.tumble.commands;
-
-import com.MylesAndMore.tumble.TumbleManager;
-import org.bukkit.ChatColor;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.CommandSender;
-
-public class ReloadCommand implements CommandExecutor {
- @Override
- public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
- // Check if the sender has perms to run command
- if (sender.hasPermission("tumble.reload")) {
- // If sender does have permission, reload the plugin's config and display a confirmation message
- TumbleManager.getPlugin().reloadConfig();
- sender.sendMessage(ChatColor.GREEN + "Tumble configuration reloaded successfully.");
- }
- else {
- // If sender does not have permission, display them the permissionMessage from the config
- sender.sendMessage(ChatColor.RED + TumbleManager.getPermissionMessage());
- }
- return true;
- }
-}
diff --git a/src/main/java/com/MylesAndMore/tumble/commands/SetAutoStart.java b/src/main/java/com/MylesAndMore/tumble/commands/SetAutoStart.java
deleted file mode 100644
index b5339b5..0000000
--- a/src/main/java/com/MylesAndMore/tumble/commands/SetAutoStart.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package com.MylesAndMore.tumble.commands;
-
-import com.MylesAndMore.tumble.TumbleManager;
-import org.bukkit.ChatColor;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.CommandSender;
-
-import java.util.Objects;
-
-public class SetAutoStart implements CommandExecutor{
- @Override
- public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
- // Check if sender has perms to run command
- if (sender.hasPermission("tumble.autostart")) {
- // Check if game and lobby worlds are null
- if (TumbleManager.getGameWorld() != null) {
- if (TumbleManager.getLobbyWorld() != null) {
- // Check the amount of args entered
- if (args.length == 2) {
- // Check the player # argument and parse it into an int
- int args0;
- try {
- args0 = Integer.parseInt(args[0]);
- } catch (NumberFormatException nfe){
- sender.sendMessage(ChatColor.RED + "Player amount must be a valid number.");
- return true;
- } catch (Exception e){
- sender.sendMessage(ChatColor.RED + "Invalid player amount.");
- return true;
- }
- // PlayerAmount & enable/disable were entered
- // Check if a playerAmount between 2-8 was entered
- if ((args0 >= 2) && (args0 <= 8)) {
- if (Objects.equals(args[1], "enable")) {
- // Write values to the config
- TumbleManager.getPlugin().getConfig().set("autoStart.players", args0);
- TumbleManager.getPlugin().getConfig().set("autoStart.enabled", true);
- TumbleManager.getPlugin().saveConfig();
- sender.sendMessage(ChatColor.GREEN + "Configuration saved!");
- sender.sendMessage(ChatColor.GREEN + "Run " + ChatColor.GRAY + "/tumble:reload " + ChatColor.GREEN + "the changes to take effect.");
- }
- else if (Objects.equals(args[1], "disable")) {
- TumbleManager.getPlugin().getConfig().set("autoStart.players", args0);
- TumbleManager.getPlugin().getConfig().set("autoStart.enabled", false);
- TumbleManager.getPlugin().saveConfig();
- sender.sendMessage(ChatColor.GREEN + "Configuration saved!");
- sender.sendMessage(ChatColor.GREEN + "Run " + ChatColor.GRAY + "/tumble:reload " + ChatColor.GREEN + "the changes to take effect.");
- }
- else {
- return false;
- }
- }
- else {
- sender.sendMessage(ChatColor.RED + "Please enter a player amount between two and eight!");
- }
- }
- else if (args.length == 1) {
- // Only PlayerAmount was entered
- int args0;
- try {
- args0 = Integer.parseInt(args[0]);
- } catch (NumberFormatException nfe){
- sender.sendMessage(ChatColor.RED + "Player amount must be a valid number.");
- return true;
- } catch (Exception e){
- sender.sendMessage(ChatColor.RED + "Invalid player amount.");
- return true;
- }
- if ((args0 >= 2) && (args0 <= 8)) {
- TumbleManager.getPlugin().getConfig().set("autoStart.players", args0);
- TumbleManager.getPlugin().saveConfig();
- sender.sendMessage(ChatColor.GREEN + "Configuration saved!");
- sender.sendMessage(ChatColor.GREEN + "Run " + ChatColor.GRAY + "/tumble:reload " + ChatColor.GREEN + "the changes to take effect.");
- }
- else {
- sender.sendMessage(ChatColor.RED + "Please enter a player amount between two and eight!");
- }
- }
- else {
- return false;
- }
- }
- else {
- sender.sendMessage(ChatColor.RED + "Please link a lobby world first!");
- }
- }
- else {
- sender.sendMessage(ChatColor.RED + "Please link a game world first!");
- }
- }
- else {
- sender.sendMessage(ChatColor.RED + TumbleManager.getPermissionMessage());
- }
- return true;
- }
-}
diff --git a/src/main/java/com/MylesAndMore/tumble/commands/SetWinnerLoc.java b/src/main/java/com/MylesAndMore/tumble/commands/SetWinnerLoc.java
deleted file mode 100644
index ec145d1..0000000
--- a/src/main/java/com/MylesAndMore/tumble/commands/SetWinnerLoc.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package com.MylesAndMore.tumble.commands;
-
-import com.MylesAndMore.tumble.TumbleManager;
-import org.bukkit.ChatColor;
-import org.bukkit.Location;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.command.ConsoleCommandSender;
-import org.bukkit.entity.Player;
-
-public class SetWinnerLoc implements CommandExecutor {
- @Override
- public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
- // Check if sender has perms to run command
- if (sender.hasPermission("tumble.winlocation")) {
- // Check if the lobby world has been configured
- if (TumbleManager.getLobbyWorld() != null) {
- // Check if the sender is a player
- if (sender instanceof Player) {
- // Check the sender entered the correct number of args
- if (args.length == 3) {
- double args0 = 0;
- double args1 = 0;
- double args2 = 0;
- try {
- args0 = Double.parseDouble(args[0]);
- args1 = Double.parseDouble(args[1]);
- args2 = Double.parseDouble(args[2]);
- } catch (NumberFormatException nfe){
- sender.sendMessage(ChatColor.RED + "Input arguments must be valid numbers.");
- } catch (Exception e){
- sender.sendMessage(ChatColor.RED + "Invalid input arguments.");
- }
- // Check if any of the args were 0 (this will cause future problems so we prevent it here)
- if (!((args0 == 0) || (args1 == 0) || (args2 == 0))) {
- TumbleManager.getPlugin().getConfig().set("winnerTeleport.x", args0);
- TumbleManager.getPlugin().getConfig().set("winnerTeleport.y", args1);
- TumbleManager.getPlugin().getConfig().set("winnerTeleport.z", args2);
- TumbleManager.getPlugin().saveConfig();
- sender.sendMessage(ChatColor.GREEN + "Win location successfully set!");
- sender.sendMessage(ChatColor.GREEN + "Run " + ChatColor.GRAY + "/tumble:reload " + ChatColor.GREEN + "the changes to take effect.");
- }
- else {
- sender.sendMessage(ChatColor.RED + "Your coordinates cannot be zero!");
- sender.sendMessage(ChatColor.RED + "Use something like 0.5 (the middle of the block) instead.");
- }
- }
- // If the sender entered no args, use their current location
- else if (args.length == 0) {
- Location senderPos = ((Player) sender).getLocation();
- // if so, check if any of their locations are zero
- if (!((senderPos.getX() == 0) || (senderPos.getY() == 0) || (senderPos.getZ() == 0))) {
- // set the config values to their current pos
- TumbleManager.getPlugin().getConfig().set("winnerTeleport.x", senderPos.getX());
- TumbleManager.getPlugin().getConfig().set("winnerTeleport.y", senderPos.getY());
- TumbleManager.getPlugin().getConfig().set("winnerTeleport.z", senderPos.getZ());
- TumbleManager.getPlugin().saveConfig();
- sender.sendMessage(ChatColor.GREEN + "Win location successfully set!");
- sender.sendMessage(ChatColor.GREEN + "Run " + ChatColor.GRAY + "/tumble:reload " + ChatColor.GREEN + "the changes to take effect.");
- }
- else {
- sender.sendMessage(ChatColor.RED + "Your coordinates cannot be zero!");
- sender.sendMessage(ChatColor.RED + "Use something like 0.5 (the middle of the block) instead.");
- }
- }
- else {
- return false;
- }
- }
- // Check if the sender is the console
- else if (sender instanceof ConsoleCommandSender) {
- // Check if the correct # of args were entered
- if (args.length == 3) {
- double args0 = 0;
- double args1 = 0;
- double args2 = 0;
- try {
- args0 = Double.parseDouble(args[0]);
- args1 = Double.parseDouble(args[1]);
- args2 = Double.parseDouble(args[2]);
- } catch (NumberFormatException nfe){
- sender.sendMessage(ChatColor.RED + "Input arguments must be valid numbers.");
- } catch (Exception e){
- sender.sendMessage(ChatColor.RED + "Invalid input arguments.");
- }
- // Check if any of the args were 0 (this will cause future problems so we prevent it here)
- if (!((args0 == 0) || (args1 == 0) || (args2 == 0))) {
- TumbleManager.getPlugin().getConfig().set("winnerTeleport.x", args0);
- TumbleManager.getPlugin().getConfig().set("winnerTeleport.y", args1);
- TumbleManager.getPlugin().getConfig().set("winnerTeleport.z", args2);
- TumbleManager.getPlugin().saveConfig();
- sender.sendMessage(ChatColor.GREEN + "Win location successfully set!");
- sender.sendMessage(ChatColor.GREEN + "Run " + ChatColor.GRAY + "/tumble:reload " + ChatColor.GREEN + "the changes to take effect.");
- }
- else {
- sender.sendMessage(ChatColor.RED + "Your coordinates cannot be zero!");
- sender.sendMessage(ChatColor.RED + "Use something like 0.5 (the middle of the block) instead.");
- }
- }
- else {
- return false;
- }
- }
- }
- else {
- sender.sendMessage(ChatColor.RED + "Please link a lobby world first!");
- }
- }
- else {
- sender.sendMessage(ChatColor.RED + TumbleManager.getPermissionMessage());
- }
- return true;
- }
-}
diff --git a/src/main/java/com/MylesAndMore/tumble/commands/SetWorldConfig.java b/src/main/java/com/MylesAndMore/tumble/commands/SetWorldConfig.java
deleted file mode 100644
index 695c248..0000000
--- a/src/main/java/com/MylesAndMore/tumble/commands/SetWorldConfig.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.MylesAndMore.tumble.commands;
-
-import com.MylesAndMore.tumble.TumbleManager;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.GameRule;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.CommandSender;
-
-import java.util.Objects;
-
-public class SetWorldConfig implements CommandExecutor {
- @Override
- public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
- // Catch for null arguments
- if (args.length == 2) {
- // Check if sender has perms to run command
- if (sender.hasPermission("tumble.link")){
- // Initialize vars for their respective command arguments
- String world = args[0];
- String worldType = args[1];
- // Check if the world type is lobby
- if (Objects.equals(worldType, "lobby")) {
- // Check if the world is actually a world on the server
- if (Bukkit.getWorld(world) != null) {
- // Check if the world has already been configured
- if (!Objects.equals(TumbleManager.getGameWorld(), world)) {
- // Set the specified value of the world in the config under lobbyWorld
- TumbleManager.getPlugin().getConfig().set("lobbyWorld", world);
- // Save said config
- TumbleManager.getPlugin().saveConfig();
- // Feedback
- sender.sendMessage(ChatColor.GREEN + "Lobby world successfully linked: " + ChatColor.GRAY + world);
- sender.sendMessage(ChatColor.GREEN + "Please restart your server for the changes to take effect; " + ChatColor.RED + "reloading the plugin is insufficient!");
- }
- // Feedback for duplicate world configuration
- else {
- sender.sendMessage(ChatColor.RED + "That world has already been linked, please choose/create another world!");
- }
- }
- // Feedback for if the world doesn't exist
- else {
- sender.sendMessage(ChatColor.RED + "Failed to find a world named " + ChatColor.GRAY + world);
- }
- }
- // Check if the world type is game
- else if (Objects.equals(args[1], "game")) {
- if (Bukkit.getWorld(world) != null) {
- if (!Objects.equals(TumbleManager.getLobbyWorld(), world)) {
- TumbleManager.getPlugin().getConfig().set("gameWorld", world);
- TumbleManager.getPlugin().saveConfig();
- // Set the gamerule of doImmediateRespawn in the gameWorld for later
- Bukkit.getWorld(world).setGameRule(GameRule.DO_IMMEDIATE_RESPAWN, true);
- Bukkit.getWorld(world).setGameRule(GameRule.KEEP_INVENTORY, true);
- sender.sendMessage(ChatColor.GREEN + "Game world successfully linked: " + ChatColor.GRAY + world);
- sender.sendMessage(ChatColor.GREEN + "Please restart your server for the changes to take effect; " + ChatColor.RED + "reloading the plugin is insufficient!");
- }
- else {
- sender.sendMessage(ChatColor.RED + "That world has already been linked, please choose/create another world!");
- }
- }
- else {
- sender.sendMessage(ChatColor.RED + "Failed to find a world named " + ChatColor.GRAY + world);
- }
- }
- // Feedback for if lobby or game wasn't entered
- else {
- sender.sendMessage(ChatColor.RED + "Allowed world types are " + ChatColor.GRAY + "lobby " + ChatColor.RED + "and " + ChatColor.GRAY + "game" + ChatColor.RED + ".");
- }
- }
- // Feedback for if sender has no perms
- else {
- sender.sendMessage(ChatColor.RED + TumbleManager.getPermissionMessage());
- }
- }
- // Feedback for if no args were entered
- else {
- return false;
- }
- return true;
- }
-}
diff --git a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java
deleted file mode 100644
index c138cda..0000000
--- a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package com.MylesAndMore.tumble.commands;
-
-import com.MylesAndMore.tumble.Game;
-import com.MylesAndMore.tumble.TumbleManager;
-import org.bukkit.ChatColor;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.CommandSender;
-
-import java.util.Objects;
-
-public class StartGame implements CommandExecutor {
- @Override
- public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
- // Check if sender has perms to run command
- if (sender.hasPermission("tumble.start")) {
- // Check if there is a lobbyWorld specified in config
- if (TumbleManager.getLobbyWorld() != null) {
- // Check if there is more than one person in lobby
- if (TumbleManager.getPlayersInLobby().size() > 1) {
- // Check if there is a gameWorld specified in config
- if (TumbleManager.getGameWorld() != null) {
- // Check if a game is already pending to start
- if (!Objects.equals(Game.getGame().getGameState(), "waiting")) {
- sender.sendMessage(ChatColor.BLUE + "Generating layers, please wait.");
- // Use multiverse to load game world
- // If the load was successful, start game
- if (TumbleManager.getMVWorldManager().loadWorld(TumbleManager.getGameWorld())) {
- // If there is no starting argument,
- if (args.length == 0) {
- // pull which gamemode to initiate from the config file
- if (!Game.getGame().startGame(TumbleManager.getGameType())) {
- // Sender feedback for if the game failed to start
- if (Objects.equals(Game.getGame().getGameState(), "starting")) {
- sender.sendMessage(ChatColor.RED + "A game is already starting!");
- }
- else if (Objects.equals(Game.getGame().getGameState(), "running")) {
- sender.sendMessage(ChatColor.RED + "A game is already running!");
- }
- else {
- sender.sendMessage(ChatColor.RED + "Failed to recognize game of type " + ChatColor.GRAY + TumbleManager.getPlugin().getConfig().getString("gameMode"));
- }
- }
- }
- // If there was an argument for gameType, pass that into the startGame method
- else {
- if (!Game.getGame().startGame(args[0])) {
- // Sender feedback for if the game failed to start
- if (Objects.equals(Game.getGame().getGameState(), "starting")) {
- sender.sendMessage(ChatColor.RED + "A game is already starting!");
- }
- else if (Objects.equals(Game.getGame().getGameState(), "running")) {
- sender.sendMessage(ChatColor.RED + "A game is already running!");
- }
- else {
- sender.sendMessage(ChatColor.RED + "Failed to recognize game of type " + ChatColor.GRAY + args[0]);
- }
- }
- }
- }
- // If load was unsuccessful, give feedback
- // Note: this should not occur unless the config file was edited externally,
- // because the plugin prevents adding "worlds" that are not actually present to the config.
- else {
- sender.sendMessage(ChatColor.RED + "Failed to find a world named " + ChatColor.GRAY + TumbleManager.getGameWorld());
- sender.sendMessage(ChatColor.RED + "Is the configuration file correct?");
- }
- }
- else {
- sender.sendMessage(ChatColor.RED + "A game is already queued to begin!");
- }
- }
- // Feedback for if there is no gameWorld in the config
- else {
- sender.sendMessage(ChatColor.RED + "Please link a game world first!");
- }
- }
- // Feedback for if there is only one person online
- else {
- sender.sendMessage(ChatColor.RED + "You can't start a game with yourself!");
- }
- }
- else {
- sender.sendMessage(ChatColor.RED + "Please link a lobby world first!");
- }
- }
- // Feedback for if the sender has no perms
- else {
- sender.sendMessage(ChatColor.RED + TumbleManager.getPermissionMessage());
- }
- return true;
- }
-}