aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/MylesAndMore
diff options
context:
space:
mode:
authorMyles <43725835+MylesAndMore@users.noreply.github.com>2022-12-13 14:16:59 -0600
committerGitHub <noreply@github.com>2022-12-13 14:16:59 -0600
commit6739bbb14d03bd215f8c7d72dc14d961b6bc175e (patch)
treee2c680914445931fdfad35169eb17dd0404301f5 /src/main/java/com/MylesAndMore
parentcea002dc786f7826a1a3faef26fb659e3d8e908e (diff)
parentcbafd10bc90273a263d019faeccb356ead442eb1 (diff)
downloadTumble-6739bbb14d03bd215f8c7d72dc14d961b6bc175e.tar.gz
Tumble-6739bbb14d03bd215f8c7d72dc14d961b6bc175e.tar.bz2
Tumble-6739bbb14d03bd215f8c7d72dc14d961b6bc175e.zip
Merge pull request #1 from MylesAndMore/beta
merge beta to main for release
Diffstat (limited to 'src/main/java/com/MylesAndMore')
-rw-r--r--src/main/java/com/MylesAndMore/tumble/EventListener.java277
-rw-r--r--src/main/java/com/MylesAndMore/tumble/Game.java593
-rw-r--r--src/main/java/com/MylesAndMore/tumble/GameManager.java60
-rw-r--r--src/main/java/com/MylesAndMore/tumble/Main.java17
-rw-r--r--src/main/java/com/MylesAndMore/tumble/TumbleManager.java4
-rw-r--r--src/main/java/com/MylesAndMore/tumble/api/Generator.java97
-rw-r--r--src/main/java/com/MylesAndMore/tumble/api/Layers.java300
-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.java4
-rw-r--r--src/main/java/com/MylesAndMore/tumble/commands/StartGame.java93
11 files changed, 1527 insertions, 130 deletions
diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java
index 6c20a80..5e46e87 100644
--- a/src/main/java/com/MylesAndMore/tumble/EventListener.java
+++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java
@@ -1,37 +1,284 @@
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.player.PlayerJoinEvent;
-import org.bukkit.event.player.PlayerQuitEvent;
+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.player.*;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.util.Vector;
-public class EventListener implements Listener{
+/**
+ * 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)
+ 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);
}
- // If the gameWorld and lobbyWorld is not null, then check
- if (TumbleManager.getGameWorld() != null && TumbleManager.getLobbyWorld() != null) {
- // if the player joining is in the game world, then
- if (event.getPlayer().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) {
- // send them back to the lobby.
- event.getPlayer().teleport(Bukkit.getWorld(TumbleManager.getLobbyWorld()).getSpawnLocation());
+ // 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 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)
+ 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);
+ }
+ }
+ }
}
}
diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java
new file mode 100644
index 0000000..91c2770
--- /dev/null
+++ b/src/main/java/com/MylesAndMore/tumble/Game.java
@@ -0,0 +1,593 @@
+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));
+ // 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.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.SNOW_BLOCK), layers.getMaterialList());
+ }
+ else if (Random.nextInt(4) == 2) {
+ // Multi-tiered circle
+ Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.SNOW_BLOCK), layers.getMaterialList());
+ 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.getMaterialList());
+ 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.getMaterialList());
+ 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.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());
+ 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.getMaterialList());
+ 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.getMaterialList());
+ 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.getMaterialList());
+ 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.getMaterialList());
+ 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.getMaterialList());
+ 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.getMaterialList());
+ 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/GameManager.java b/src/main/java/com/MylesAndMore/tumble/GameManager.java
deleted file mode 100644
index a778c7d..0000000
--- a/src/main/java/com/MylesAndMore/tumble/GameManager.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.MylesAndMore.tumble;
-
-import com.MylesAndMore.tumble.api.Generator;
-import org.bukkit.Bukkit;
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-
-import java.util.List;
-import java.util.Objects;
-
-public class GameManager {
- public static boolean createGame(String gameType) {
- if (Objects.equals(gameType, "shovels")) {
- // Generate layers
- Location layer = Bukkit.getWorld(TumbleManager.getGameWorld()).getSpawnLocation();
- layer.setY(layer.getY() - 1);
- Generator.generateLayer(layer, 17, 1, Material.SNOW_BLOCK);
- Generator.generateLayer(layer, 13, 1, Material.AIR);
- layer.setY(layer.getY() - 1);
- Generator.generateLayer(layer, 13, 1, Material.GRASS_BLOCK);
- layer.setY(layer.getY() - 1);
- Generator.generateLayer(layer, 4, 1, Material.PODZOL);
- layer.setY(layer.getY() + 1);
- Generator.generateLayer(layer, 4, 2, Material.GRASS);
- // Give players diamond shovels
- giveItems(new ItemStack(Material.DIAMOND_SHOVEL));
- // Pass on the game type
-
- }
- else if (Objects.equals(gameType, "snowballs")) {
- // Generate three layers
- // (Will make this customizable in later versions)
- // Remember, the snowballs don't interact with players!
-
- // Give players infinite snowballs
-
- // Pass on the game type
- }
- else if (Objects.equals(gameType, "mixed")) {
- // Randomly select rounds from above
-
- // Pass on the game type
- }
- else {
- return false;
- }
- return true;
- }
-
- public static void giveItems(ItemStack itemStack) {
- for (List<Player> playersWithoutItem = TumbleManager.getPlayersInLobby(); playersWithoutItem.size() > 0; playersWithoutItem.remove(0)) {
- // Get a singular player from the player list
- Player playerWithoutItem = playersWithoutItem.get(0);
- // Give that player the specified item
- playerWithoutItem.getInventory().addItem(itemStack);
- }
- }
-}
diff --git a/src/main/java/com/MylesAndMore/tumble/Main.java b/src/main/java/com/MylesAndMore/tumble/Main.java
index 513b7d1..73dedf5 100644
--- a/src/main/java/com/MylesAndMore/tumble/Main.java
+++ b/src/main/java/com/MylesAndMore/tumble/Main.java
@@ -1,9 +1,7 @@
package com.MylesAndMore.tumble;
-import com.MylesAndMore.tumble.commands.ReloadCommand;
+import com.MylesAndMore.tumble.commands.*;
import com.MylesAndMore.tumble.api.Metrics;
-import com.MylesAndMore.tumble.commands.SetWorldConfig;
-import com.MylesAndMore.tumble.commands.StartGame;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
@@ -16,6 +14,8 @@ public class Main extends JavaPlugin{
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();
@@ -25,12 +25,15 @@ public class Main extends JavaPlugin{
// Check if worlds are null in config
if (TumbleManager.getGameWorld() == null) {
- Bukkit.getServer().getLogger().warning("It appears you have not configured a game world for Tumble.");
- Bukkit.getServer().getLogger().info("If this is your first time running the plugin, you may disregard this message.");
+ 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("It appears you have not configured a lobby world for Tumble.");
- Bukkit.getServer().getLogger().info("If this is your first time running the plugin, you may disregard this message.");
+ 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
index 0b62494..43cc241 100644
--- a/src/main/java/com/MylesAndMore/tumble/TumbleManager.java
+++ b/src/main/java/com/MylesAndMore/tumble/TumbleManager.java
@@ -8,6 +8,9 @@ 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() {
@@ -18,6 +21,7 @@ public class TumbleManager {
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(); }
diff --git a/src/main/java/com/MylesAndMore/tumble/api/Generator.java b/src/main/java/com/MylesAndMore/tumble/api/Generator.java
index 632627d..db8bacc 100644
--- a/src/main/java/com/MylesAndMore/tumble/api/Generator.java
+++ b/src/main/java/com/MylesAndMore/tumble/api/Generator.java
@@ -3,13 +3,34 @@ 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 {
- public static void generateLayer(Location center, int radius, int height, Material material) {
+ /**
+ * 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;
@@ -17,11 +38,83 @@ public class Generator {
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) {
- Location block = new Location(world, x, y, z);
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
new file mode 100644
index 0000000..8818631
--- /dev/null
+++ b/src/main/java/com/MylesAndMore/tumble/api/Layers.java
@@ -0,0 +1,300 @@
+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(){
+ // Make the other layers more common than the glass layer
+ for (int i = 0; i < 10; i++) {
+ 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(gen15);
+ matList.add(gen16);
+ }
+ // Glass layer
+ matList.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()));
+ }
+
+ // Define the list that will store the material lists
+ private final List<List<Material>> matList = new ArrayList<>();
+
+
+ // 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.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> 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);
+ }};
+
+}
diff --git a/src/main/java/com/MylesAndMore/tumble/commands/SetAutoStart.java b/src/main/java/com/MylesAndMore/tumble/commands/SetAutoStart.java
new file mode 100644
index 0000000..4b97d9a
--- /dev/null
+++ b/src/main/java/com/MylesAndMore/tumble/commands/SetAutoStart.java
@@ -0,0 +1,97 @@
+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("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
new file mode 100644
index 0000000..ec145d1
--- /dev/null
+++ b/src/main/java/com/MylesAndMore/tumble/commands/SetWinnerLoc.java
@@ -0,0 +1,115 @@
+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
index d27a5a8..695c248 100644
--- a/src/main/java/com/MylesAndMore/tumble/commands/SetWorldConfig.java
+++ b/src/main/java/com/MylesAndMore/tumble/commands/SetWorldConfig.java
@@ -3,6 +3,7 @@ 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;
@@ -49,6 +50,9 @@ public class SetWorldConfig implements CommandExecutor {
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!");
}
diff --git a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java
index 9daa959..c138cda 100644
--- a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java
+++ b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java
@@ -1,19 +1,17 @@
package com.MylesAndMore.tumble.commands;
-import com.MylesAndMore.tumble.GameManager;
+import com.MylesAndMore.tumble.Game;
import com.MylesAndMore.tumble.TumbleManager;
-import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import java.util.List;
+import java.util.Objects;
public class StartGame implements CommandExecutor {
- // Define the startGame method so that other classes can refrence it
- public void startGame(CommandSender sender, String[] args) {
+ @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
@@ -22,28 +20,54 @@ public class StartGame implements CommandExecutor {
if (TumbleManager.getPlayersInLobby().size() > 1) {
// Check if there is a gameWorld specified in config
if (TumbleManager.getGameWorld() != null) {
- sender.sendMessage("Checking world, this could take a few moments...");
- // Use multiverse to load game world
- // If the load was successful, start game
- if (TumbleManager.getMVWorldManager().loadWorld(TumbleManager.getGameWorld())) {
- sender.sendMessage("Generating layers...");
- // Check which gamemode to initiate from the config file
- if (GameManager.createGame(TumbleManager.getPlugin().getConfig().getString("gameMode"))) {
- // If game type exists, send players to the world
- // At this point, layers have been generated, and items have been allotted from the createGame method
- sendWorld();
+ // 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 {
- // If game type does not exist, give sender feedback
- sender.sendMessage(ChatColor.RED + "Failed to recognize game of type " + ChatColor.GRAY + TumbleManager.getPlugin().getConfig().getString("gameMode"));
+ sender.sendMessage(ChatColor.RED + "Failed to find a world named " + ChatColor.GRAY + TumbleManager.getGameWorld());
+ sender.sendMessage(ChatColor.RED + "Is the configuration file correct?");
}
}
- // 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?");
+ sender.sendMessage(ChatColor.RED + "A game is already queued to begin!");
}
}
// Feedback for if there is no gameWorld in the config
@@ -64,29 +88,6 @@ public class StartGame implements CommandExecutor {
else {
sender.sendMessage(ChatColor.RED + TumbleManager.getPermissionMessage());
}
- }
-
- public void sendWorld() {
- // Create Locations to scatter players around the first layer
-
- // While there are still players in the lobby, send them to the gameWorld
- // This is just a way of sending everybody in the lobby to the game
- for (List<Player> playersInLobby = TumbleManager.getPlayersInLobby(); playersInLobby.size() > 0; playersInLobby = TumbleManager.getPlayersInLobby()) {
- // Get a singular player from the player list
- Player aPlayer = playersInLobby.get(0);
- // Teleport that player to the spawn of the gameWorld
- aPlayer.teleport(Bukkit.getWorld(TumbleManager.getGameWorld()).getSpawnLocation());
- }
-
- // Add a little break because it can take the clients a bit to load into the new world
- // Then, transition to another method because this one is getting really long
- // In that method: set a flag to monitor the playerDeathEvent so we know when all the players have died
- // Also start music
- }
-
- @Override
- public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
- startGame(sender, args);
return true;
}
}