diff options
| author | sowgro <tpoke.ferrari@gmail.com> | 2024-08-01 17:38:44 -0400 | 
|---|---|---|
| committer | sowgro <tpoke.ferrari@gmail.com> | 2024-08-01 17:38:44 -0400 | 
| commit | f049b84bbd3d9354f9cba949cf71dc4a6fba0786 (patch) | |
| tree | b04bf87a5939c362c5c43d4a380adeedec02fed1 | |
| parent | 8c9889930cf61f959cc60e5a0098ece4215c59f2 (diff) | |
| parent | cadddd7499f92b4529ce34231ff4a379011515ff (diff) | |
| download | Tumble-f049b84bbd3d9354f9cba949cf71dc4a6fba0786.tar.gz Tumble-f049b84bbd3d9354f9cba949cf71dc4a6fba0786.tar.bz2 Tumble-f049b84bbd3d9354f9cba949cf71dc4a6fba0786.zip | |
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	src/main/java/com/MylesAndMore/Tumble/game/Generator.java
#	src/main/java/com/MylesAndMore/Tumble/game/Layers.java
27 files changed, 277 insertions, 288 deletions
| diff --git a/OG_GUIDE.md b/OG_GUIDE.md index f7302a1..da75d93 100644 --- a/OG_GUIDE.md +++ b/OG_GUIDE.md @@ -16,7 +16,7 @@ In this guide, I'll go over how to set up the Tumble plugin with the original ga      Tip: set a specific directory to store your worlds in with the `world-container` setting in `bukkit.yml` -3. Set `level-name` in server.properities to `lobby` +3. Set `level-name` in server.properties to `lobby`  4. Take note of the names of the world folders, we will need this in a moment.  5. Start and join your server.  6. Import your arena worlds. This can be done with the multiverse command `/mv import <your-world-name> normal` @@ -93,25 +93,25 @@ In this guide, I'll go over how to set up the Tumble plugin with the original ga           z: -340.5           world: lobby     ``` -8. Reload the plugin with `/tmbl reload`. +8. Reload the plugin with `/tumble reload`. -9. Join the game using `/tmbl join basic mixed` +9. Join the game using `/tumble join basic mixed`  (swap the arena and game type for whichever one you want to play).  You're done! Happy playing!  ## Recommended plugins +These plugins, while not required, can help to provide a more thorough minigame experience. +  - [WorldGuard](https://dev.bukkit.org/projects/worldguard) and [CyberWorldReset](https://www.spigotmc.org/resources/cyberworldreset-standard-%E2%9C%A8-regenerate-worlds-scheduled-resets-lag-optimized%E3%80%8C1-8-1-19%E3%80%8D.96834/) -Protect players from breaking blocks in the lobby and reset any redstone they activated. +   - Protect players from breaking blocks in the lobby and reset any redstone they activated.  - [ViaVersion](https://www.spigotmc.org/resources/viaversion.19254/) and [ViaBackwards](https://www.spigotmc.org/resources/viabackwards.27448/) -Allow older and newer clients to connect to your server. +   - Allow older and newer players to connect to your server.  - [Geyser](https://geysermc.org/download#geyser) and [Floodgate](https://geysermc.org/download#floodgate) -Allow Bedrock clients to connect to your server. - -- [ProtectEnviromnemt](https://www.spigotmc.org/resources/protectenvironment.82736/) -Stop water and lava flow (useful for Halloween map) - +   - Allow Bedrock clients to connect to your server. +- [ProtectEnvironment](https://www.spigotmc.org/resources/protectenvironment.82736/) +   - Stop water and lava flow (useful for Halloween map). @@ -11,73 +11,73 @@ But in Tumble, you play on randomly generated layers of blocks, using shovels, s  ## Features   -- Choose from three different game modes present in the original game: shovels, snowballs, and mixed   -- Four types of random layer generation   +- Choose from three different game modes present in the original game: shovels, snowballs, and mixed +- Four types of random layer generation  - 15 unique, themed layer varieties  - Quick and easy setup and use -- Support for 2-8 players   -- Highly customizable   -- Open-source codebase   +- Support for 2-8 players  - Multiple arenas and concurrent games -- Heavily configurable +- Highly customizable, heavily configurable +- Open-source codebase  ## Setup -1. [Download](https://github.com/MylesAndMore/tmbl/releases) the plugin's JAR file and place it in your server's plugins directory. -2. Place the worlds for your lobby and arenas in your plugins worlds directory. +1. [Download](https://github.com/MylesAndMore/tumble/releases) the plugin's JAR file and place it in your server's plugins directory. +2. Place the worlds for your lobby and arenas in your server's worlds directory.      - If you would like an experience similar to the original game, see [my guide](OG_GUIDE.md) for using the original worlds.    3. Start your server.  4. Import your worlds using a plugin like Multiverse. ```/mv import myWorld normal```. -5. Create your first arena `/tmbl create myArena` -6. Set the spawn point of the arena `/tmbl setgamespawn myArena` +5. Create your first arena `/tumble create myArena` +6. Set the spawn point of the arena `/tumble setgamespawn myArena`     - **Note**: The layers will generate relative to this location. Ensure that the area is clear, 20 blocks in each direction. -7. You're done! You can now join the game ```/tmbl join myArena mixed```. +7. You're done! You can now join the game ```/tumble join myArena mixed```.  Scroll down for more options to configure your game.    ## Commands / Permissions -| Command                             | Description                                                                        | Permission              | -|-------------------------------------|------------------------------------------------------------------------------------|-------------------------| -| `/tmbl join <arenaName> [gameType]` | Join a Tumble match. Can infer game type if a game is already started in the arena | `tumble.join`           | -| `/tmbl leave`                       | Quit a Tumble match                                                                | `tumble.leave`          | -| `/tmbl forcestart [arenaName]`      | Force start a Tumble match. Can infer arena if you are in one                      | `tumble.forcestart`     | -| `/tmbl forcestop [arenaName]`       | Force stop a Tumble match. Can infer arena if you are in one                       | `tumble.forcestop`      | -| `/tmbl reload`                      | Reload the plugin's configs.                                                       | `tumble.reload`         | -| `/tmbl create <arenaName>`          | Create a new arena                                                                 | `tumble.create`         | -| `/tmbl remove <arenaName>`          | Remove an arena                                                                    | `tumble.remove`         | -| `/tmbl setgamespawn <arenaName>`    | Set game spawn to your current position                                            | `tumble.setgamespawn`   | -| `/tmbl setkillylevel <arenaName>`   | Set the arena's Y-level to kill players at to current Y coordinate                 | `tumble.setkillylevel`  | -| `/tmbl setlobby <arenaName>`        | Set the arena's lobby to current location                                          | `tumble.setlobby`       | -| `/tmbl setwaitarea <arenaName>`     | Set the arena's wait area to the current location                                  | `tumble.setwaitarea`    | -| `/tmbl setwinnerlobby <arenaName>`  | Set the arena's lobby to the current location                                      | `tumble.setwinnerlobby` | - +| Command                               | Description                                                                         | Permission              | +|---------------------------------------|-------------------------------------------------------------------------------------|-------------------------| +| `/tumble join <arenaName> [gameType]` | Join a Tumble match. Can infer game type if a game is already started in the arena. | `tumble.join`           | +| `/tumble leave`                       | Leave a Tumble match.                                                               | `tumble.leave`          | +| `/tumble forcestart [arenaName]`      | Force start a Tumble match. Can infer arena if you are in one.                      | `tumble.forcestart`     | +| `/tumble forcestop [arenaName]`       | Force stop a Tumble match. Can infer arena if you are in one.                       | `tumble.forcestop`      | +| `/tumble reload`                      | Reload the plugin's configuration.                                                  | `tumble.reload`         | +| `/tumble create <arenaName>`          | Create a new arena.                                                                 | `tumble.create`         | +| `/tumble remove <arenaName>`          | Remove an arena.                                                                    | `tumble.remove`         | +| `/tumble setgamespawn <arenaName>`    | Set the arena's game spawn to your current position.                                | `tumble.setgamespawn`   | +| `/tumble setkillylevel <arenaName>`   | Set the arena's Y-level to kill players at to current Y coordinate.                 | `tumble.setkillylevel`  | +| `/tumble setlobby <arenaName>`        | Set the arena's lobby to current location.                                          | `tumble.setlobby`       | +| `/tumble setwaitarea <arenaName>`     | Set the arena's wait area to the current location.                                  | `tumble.setwaitarea`    | +| `/tumble setwinnerlobby <arenaName>`  | Set the arena's lobby to the current location.                                      | `tumble.setwinnerlobby` | + +Note that the `/tmbl` command can be used as a shorter alias to `/tumble`.  ## Configuration   -Configuration for this plugin is stored in three files. +Configuration for this plugin is stored in three files:  ### config.yml -Stores common settings - -| Option                     | Type              | Default value | -|----------------------------|-------------------|---------------| -| `hide-join-leave-messages` | Boolean           | `false`       | -| `wait-duration`            | Integer (seconds) | `15`          | +Stores general settings. +| Option                     | Type    | Description                                                                    | Default value | +|----------------------------|---------|--------------------------------------------------------------------------------|---------------| +| `hide-join-leave-messages` | Boolean | Hides player join and leave messages in public chat.                           | `false`       | +| `wait-duration`            | Integer | Duration (in seconds) to wait for more players to join a game before starting. | `15`          |  ### arenas.yml -Stores data for each arena. You may add and remove arenas as you wish. +Stores data about each arena. +Arenas may be added and removed as you wish, either via the commands detailed above or by editing the `arenas.yml` file directly.  Each arena can contain the following locations:  | Location                 | Description                                                                         |  |--------------------------|-------------------------------------------------------------------------------------|  | `game-spawn` **Required* | The location where players will be teleported, and the layers will generate around. | -| `wait-area`              | The location where players will be teleported to before the game begins             | -| `lobby`                  | The location where players will be teleported to after the game                     | -| `winner-lobby`           | The location where the winner will be teleported after the game                     | +| `wait-area`              | The location where players will be teleported to before the game begins.            | +| `lobby`                  | The location where players will be teleported to after the game.                    | +| `winner-lobby`           | The location where the winner will be teleported after the game.                    |  Locations are stored using the following format:  ```yaml @@ -87,24 +87,21 @@ Locations are stored using the following format:        z: 0.5        world: worldName  ``` +If a location is not specified, players will not be teleported by the plugin.  Each arena can also contain the following option: -| Option      | Type    | Description                                                     | -|-------------|---------|-----------------------------------------------------------------| -| `kill-at-y` | Integer | When a player falls below this Y-level, they will be eliminated | +| Option      | Type    | Description                                                      | +|-------------|---------|------------------------------------------------------------------| +| `kill-at-y` | Integer | When a player falls below this Y-level, they will be eliminated. |  ### language.yml -Most of this plugin's strings are configurable through this file. (Excluding from some console errors) +Most of this plugin's messages are configurable through this file (excluding some console errors).  All plugin chat messages will have the `prefix` prepended to them.  -Colors can be added using alternate color codes: -``` -&cRed Text -``` - +Colors can be added using alternate color codes; for example, `&cRed Text` will appear red in-game.  ## Issues & Feedback   -Feel free to report any bugs, leave feedback, ask questions, or submit ideas for new features on our [GitHub issues page](https://github.com/MylesAndMore/tmbl/issues/new)!   +Feel free to report any bugs, leave feedback, ask questions, or submit ideas for new features on the Tumble [GitHub issues page](https://github.com/MylesAndMore/tumble/issues/new)!   diff --git a/build.gradle b/build.gradle index 58b2dc8..41f2c92 100644 --- a/build.gradle +++ b/build.gradle @@ -10,18 +10,15 @@ java {  }  repositories { -    mavenCentral() // Use Maven Central for resolving dependencies. +    mavenCentral() // Use Maven Central for resolving dependencies      maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }      maven { url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' } -    maven { url "https://repo.onarandombox.com/content/groups/public/" } -    maven { url "https://repo.jeff-media.com/public/"}  }  dependencies { +    compileOnly('org.jetbrains:annotations:24.1.0')      compileOnly('org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT') -    compileOnly('com.onarandombox.multiversecore:Multiverse-Core:4.3.1')      implementation('org.bstats:bstats-bukkit:3.0.2') -    implementation('com.jeff_media:SpigotUpdateChecker:3.0.3')  }  // Disable generation of the normal JAR to reduce confusion and only generate the correctly shadowed JAR including bStats @@ -30,7 +27,6 @@ jar.finalizedBy(shadowJar)  shadowJar {      archiveBaseName.set('Tumble')      archiveClassifier.set('') -    archiveVersion.set('1.0.4') +    archiveVersion.set('2.0.0')      relocate 'org.bstats', 'com.MylesAndMore.bstats' -    relocate 'com.jeff_media.updatechecker', 'com.MylesAndMore.updatechecker'  } diff --git a/src/main/java/com/MylesAndMore/Tumble/Main.java b/src/main/java/com/MylesAndMore/Tumble/Main.java index b85636d..56a46c1 100644 --- a/src/main/java/com/MylesAndMore/Tumble/Main.java +++ b/src/main/java/com/MylesAndMore/Tumble/Main.java @@ -14,7 +14,7 @@ import org.bukkit.plugin.java.JavaPlugin;  import java.util.Objects; -public class Main extends JavaPlugin{ +public class Main extends JavaPlugin {      public static Main plugin;      @Override @@ -34,7 +34,7 @@ public class Main extends JavaPlugin{      @Override      public void onDisable() { -        // stop running games +        // Stop any running games          for (Arena a : ArenaManager.arenas.values()) {              if (a.game != null) {                  a.game.stopGame(); diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/Create.java b/src/main/java/com/MylesAndMore/Tumble/commands/Create.java index 667be5e..d60ca64 100644 --- a/src/main/java/com/MylesAndMore/Tumble/commands/Create.java +++ b/src/main/java/com/MylesAndMore/Tumble/commands/Create.java @@ -33,7 +33,7 @@ public class Create implements SubCommand, CommandExecutor, TabCompleter {          String arenaName = args[0];          ArenaManager.arenas.put(arenaName, new Arena(arenaName)); -        ArenaManager.WriteConfig(); +        ArenaManager.writeConfig();          sender.sendMessage(LanguageManager.fromKey("create-success"));          return true;      } diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/ForceStart.java b/src/main/java/com/MylesAndMore/Tumble/commands/ForceStart.java index 3953bea..29583a4 100644 --- a/src/main/java/com/MylesAndMore/Tumble/commands/ForceStart.java +++ b/src/main/java/com/MylesAndMore/Tumble/commands/ForceStart.java @@ -29,17 +29,16 @@ public class ForceStart implements SubCommand, CommandExecutor, TabCompleter {      @Override      public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { -          Game game; +          if (args.length < 1 || args[0] == null) { -            // no arena passed in, try to infer from game player is in +            // No arena passed in, try to infer from game player is in              game = ArenaManager.findGamePlayerIsIn((Player)sender);              if (game == null) {                  sender.sendMessage(LanguageManager.fromKey("missing-arena-parameter"));                  return false;              } -        } -        else { +        } else {              String arenaName = args[0];              if (!ArenaManager.arenas.containsKey(arenaName)) {                  sender.sendMessage(LanguageManager.fromKey("invalid-arena").replace("%arena%",arenaName)); diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/ForceStop.java b/src/main/java/com/MylesAndMore/Tumble/commands/ForceStop.java index 37d3465..f308979 100644 --- a/src/main/java/com/MylesAndMore/Tumble/commands/ForceStop.java +++ b/src/main/java/com/MylesAndMore/Tumble/commands/ForceStop.java @@ -31,14 +31,13 @@ public class ForceStop implements SubCommand, CommandExecutor, TabCompleter {          Game game;          if (args.length < 1 || args[0] == null) { -            // no arena passed in, try to infer from game player is in +            // No arena passed in, try to infer from game player is in              game = ArenaManager.findGamePlayerIsIn((Player)sender);              if (game == null) {                  sender.sendMessage(LanguageManager.fromKey("missing-arena-parameter"));                  return false;              } -        } -        else { +        } else {              String arenaName = args[0];              if (!ArenaManager.arenas.containsKey(arenaName)) {                  sender.sendMessage(LanguageManager.fromKey("invalid-arena").replace("%arena%",arenaName)); diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/Join.java b/src/main/java/com/MylesAndMore/Tumble/commands/Join.java index 6ce33c3..f26d4e5 100644 --- a/src/main/java/com/MylesAndMore/Tumble/commands/Join.java +++ b/src/main/java/com/MylesAndMore/Tumble/commands/Join.java @@ -50,26 +50,34 @@ public class Join implements SubCommand, CommandExecutor, TabCompleter {              return false;          }          String arenaName = args[0]; -        if (!ArenaManager.arenas.containsKey(arenaName)) -        { +        if (!ArenaManager.arenas.containsKey(arenaName)) {              sender.sendMessage(LanguageManager.fromKey("invalid-arena").replace("%arena%", arenaName));              return false;          }          Arena arena = ArenaManager.arenas.get(arenaName); +        // Check to make sure this arena has a game spawn +        if (arena.gameSpawn == null) { +            if (p.isOp()) { +                sender.sendMessage(LanguageManager.fromKey("arena-not-ready-op")); +            } else { +                sender.sendMessage(LanguageManager.fromKey("arena-not-ready")); +            } +            return false; +        } +          Game game;          if (args.length < 2 || args[1] == null) { -            // no type specified: try to infer game type from game taking place in the arena +            // No type specified: try to infer game type from game taking place in the arena              if (arena.game == null) { -                // cant infer if no game is taking place +                // Can't infer if no game is taking place                  sender.sendMessage(LanguageManager.fromKey("specify-game-type"));                  return false;              }              game = arena.game; -        } -        else { -            // type specified +        } else { +            // Game type specified              GameType type;              switch (args[1]) {                  case "shovels", "shovel"     -> type = GameType.SHOVELS; @@ -82,12 +90,10 @@ public class Join implements SubCommand, CommandExecutor, TabCompleter {              }              if (arena.game == null) { -                // no game is taking place in this arena, start one +                // No game is taking place in this arena, start one                  game = arena.game = new Game(arena, type); -            } -            else -            { -                // a game is taking place in this arena, check that it is the right type +            } else { +                // A game is taking place in this arena, check that it is the right type                  if (arena.game.type == type) {                      game = arena.game;                  } @@ -100,16 +106,7 @@ public class Join implements SubCommand, CommandExecutor, TabCompleter {              }          } -        // check to make sure the arena has a game spawn -        if (game.arena.gameSpawn == null) { -            if (p.isOp()) { -                sender.sendMessage(LanguageManager.fromKey("arena-not-ready-op")); -            } else { -                sender.sendMessage(LanguageManager.fromKey("arena-not-ready")); -            } -            return false; -        } - +        // Make sure the game isn't in progress before adding the player          if (game.gameState != GameState.WAITING) {              sender.sendMessage(LanguageManager.fromKey("game-in-progress"));              return false; diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/Reload.java b/src/main/java/com/MylesAndMore/Tumble/commands/Reload.java index 79faef9..588755f 100644 --- a/src/main/java/com/MylesAndMore/Tumble/commands/Reload.java +++ b/src/main/java/com/MylesAndMore/Tumble/commands/Reload.java @@ -29,7 +29,6 @@ public class Reload implements SubCommand, CommandExecutor, TabCompleter {      @Override      public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { -          for (Arena a : ArenaManager.arenas.values()) {              if (a.game != null) {                  a.game.stopGame(); diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/Remove.java b/src/main/java/com/MylesAndMore/Tumble/commands/Remove.java index c2aa149..9abc784 100644 --- a/src/main/java/com/MylesAndMore/Tumble/commands/Remove.java +++ b/src/main/java/com/MylesAndMore/Tumble/commands/Remove.java @@ -38,7 +38,7 @@ public class Remove implements SubCommand, CommandExecutor, TabCompleter {          }          ArenaManager.arenas.remove(arenaName); -        ArenaManager.WriteConfig(); +        ArenaManager.writeConfig();          sender.sendMessage(LanguageManager.fromKey("remove-success"));          return true;      } diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/SetGameSpawn.java b/src/main/java/com/MylesAndMore/Tumble/commands/SetGameSpawn.java index 21bdfe8..817a1a4 100644 --- a/src/main/java/com/MylesAndMore/Tumble/commands/SetGameSpawn.java +++ b/src/main/java/com/MylesAndMore/Tumble/commands/SetGameSpawn.java @@ -45,7 +45,7 @@ public class SetGameSpawn implements SubCommand, CommandExecutor, TabCompleter {          Arena arena = ArenaManager.arenas.get(arenaName);          arena.gameSpawn = ((Player)sender).getLocation(); -        ArenaManager.WriteConfig(); +        ArenaManager.writeConfig();          sender.sendMessage(LanguageManager.fromKey("set-success"));          return true;      } diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/SetKillYLevel.java b/src/main/java/com/MylesAndMore/Tumble/commands/SetKillYLevel.java index 142ffdd..27cc410 100644 --- a/src/main/java/com/MylesAndMore/Tumble/commands/SetKillYLevel.java +++ b/src/main/java/com/MylesAndMore/Tumble/commands/SetKillYLevel.java @@ -46,7 +46,7 @@ public class SetKillYLevel implements SubCommand, CommandExecutor, TabCompleter          Arena arena = ArenaManager.arenas.get(arenaName);          arena.killAtY = ((int) ((Player) sender).getLocation().getY()); -        ArenaManager.WriteConfig(); +        ArenaManager.writeConfig();          sender.sendMessage(LanguageManager.fromKey("set-success"));          return true;      } diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/SetLobby.java b/src/main/java/com/MylesAndMore/Tumble/commands/SetLobby.java index a080d08..5708643 100644 --- a/src/main/java/com/MylesAndMore/Tumble/commands/SetLobby.java +++ b/src/main/java/com/MylesAndMore/Tumble/commands/SetLobby.java @@ -45,7 +45,7 @@ public class SetLobby implements SubCommand, CommandExecutor, TabCompleter {          Arena arena = ArenaManager.arenas.get(arenaName);          arena.lobby = ((Player)sender).getLocation(); -        ArenaManager.WriteConfig(); +        ArenaManager.writeConfig();          sender.sendMessage(LanguageManager.fromKey("set-success"));          return true;      } diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/SetWaitArea.java b/src/main/java/com/MylesAndMore/Tumble/commands/SetWaitArea.java index a96e1a9..7b90099 100644 --- a/src/main/java/com/MylesAndMore/Tumble/commands/SetWaitArea.java +++ b/src/main/java/com/MylesAndMore/Tumble/commands/SetWaitArea.java @@ -45,7 +45,7 @@ public class SetWaitArea implements SubCommand, CommandExecutor, TabCompleter {          Arena arena = ArenaManager.arenas.get(arenaName);          arena.waitArea = ((Player)sender).getLocation(); -        ArenaManager.WriteConfig(); +        ArenaManager.writeConfig();          sender.sendMessage(LanguageManager.fromKey("set-success"));          return true;      } diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/SetWinnerLobby.java b/src/main/java/com/MylesAndMore/Tumble/commands/SetWinnerLobby.java index 98a535b..e0d2bea 100644 --- a/src/main/java/com/MylesAndMore/Tumble/commands/SetWinnerLobby.java +++ b/src/main/java/com/MylesAndMore/Tumble/commands/SetWinnerLobby.java @@ -45,7 +45,7 @@ public class SetWinnerLobby implements SubCommand, CommandExecutor, TabCompleter          Arena arena = ArenaManager.arenas.get(arenaName);          arena.winnerLobby = ((Player)sender).getLocation(); -        ArenaManager.WriteConfig(); +        ArenaManager.writeConfig();          sender.sendMessage(LanguageManager.fromKey("set-success"));          return true;      } diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/Tumble.java b/src/main/java/com/MylesAndMore/Tumble/commands/Tumble.java index 8b4f925..e7d1cf4 100644 --- a/src/main/java/com/MylesAndMore/Tumble/commands/Tumble.java +++ b/src/main/java/com/MylesAndMore/Tumble/commands/Tumble.java @@ -44,7 +44,7 @@ public class Tumble implements CommandExecutor, TabCompleter {              return false;          } -        // pass command action through to subCommand +        // Pass command action through to subCommand          subCmd.onCommand(sender, command, args[0], removeFirst(args));          return true;      } @@ -52,7 +52,7 @@ public class Tumble implements CommandExecutor, TabCompleter {      @Override      public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {          if (args.length == 1) { -            // show only subCommands the user has permission for +            // Show only subCommands the user has permission for              ArrayList<String> PermittedSubCmds = new ArrayList<>();              for (SubCommand subCmd: subCommands.values()) {                  if (sender.hasPermission(subCmd.getPermission())) { @@ -67,11 +67,10 @@ public class Tumble implements CommandExecutor, TabCompleter {                  return Collections.emptyList();              } -            // pass tab complete through to subCommand +            // Pass tab complete through to subCommand              if (subCommands.get(args[0]) instanceof TabCompleter tcmp) {                  return tcmp.onTabComplete(sender, command, args[0], removeFirst(args)); -            } -            else { +            } else {                  return null;              }          } diff --git a/src/main/java/com/MylesAndMore/Tumble/config/ArenaManager.java b/src/main/java/com/MylesAndMore/Tumble/config/ArenaManager.java index 5e6e571..af85b9f 100644 --- a/src/main/java/com/MylesAndMore/Tumble/config/ArenaManager.java +++ b/src/main/java/com/MylesAndMore/Tumble/config/ArenaManager.java @@ -58,44 +58,51 @@ public class ArenaManager {                  arena.waitArea = readWorld("arenas." + arenaName + ".wait-area");              } -            // validate -            if (arena.gameSpawn == null) { -                plugin.getLogger().severe("arenas.yml: Arena " + arenaName + " is missing a game spawn, before you can join you must set it with '/tmbl setgamespawn'."); -            } -            if (arena.gameSpawn == null) { -                plugin.getLogger().severe("arenas.yml: Arena " + arenaName + " is missing a lobby location. The spawn point of the default world will be used."); -            } -              arenas.put(arena.name, arena);          } +        validate(); // Validate arenas      }      /**       * Write arenas from this.arenas to arenas.yml       */ -    public static void WriteConfig() { -        config.set("arenas", null); // clear everything +    public static void writeConfig() { +        config.set("arenas", null); // Clear everything          for (Arena arena: arenas.values()) {              if (arena.killAtY != null) {                  config.set("arenas." + arena.name + ".kill-at-y", arena.killAtY);              }              if (arena.gameSpawn != null) { -                WriteWorld("arenas." + arena.name + ".game-spawn", arena.gameSpawn); +                writeWorld("arenas." + arena.name + ".game-spawn", arena.gameSpawn);              }              if (arena.lobby != null) { -                WriteWorld("arenas." + arena.name + ".lobby", arena.lobby); +                writeWorld("arenas." + arena.name + ".lobby", arena.lobby);              }              if (arena.winnerLobby != null) { -                WriteWorld("arenas." + arena.name + ".winner-lobby", arena.winnerLobby); +                writeWorld("arenas." + arena.name + ".winner-lobby", arena.winnerLobby);              }              if (arena.waitArea != null) { -                WriteWorld("arenas." + arena.name + ".wait-area", arena.waitArea); +                writeWorld("arenas." + arena.name + ".wait-area", arena.waitArea);              }          } +        validate();          arenasYml.saveConfig(); +    } +    /** +     * Check that all arenas are valid +     */ +    public static void validate() { +        for (Arena arena: arenas.values()) { +            if (arena.gameSpawn == null) { +                plugin.getLogger().severe("arenas.yml: Arena '" + arena.name + "' is missing a game spawn, before it is usable you must set a spawn with '/tumble setgamespawn'."); +            } +            if (arena.lobby == null) { +                plugin.getLogger().warning("arenas.yml: Arena '" + arena.name + "' is missing a lobby location. The spawn point of the default world will be used."); +            } +        }      }      /** @@ -123,7 +130,6 @@ public class ArenaManager {       * @return The location specified by the section, or null if the location is not valid       */      private static Location readWorld(String path) { -          ConfigurationSection section = config.getConfigurationSection(path);          if (section == null) {              plugin.getLogger().warning("arenas.yml: Error loading location at '" + path + "' - " + "Section is null"); @@ -163,8 +169,7 @@ public class ArenaManager {       * @param path The path of the section to write       * @param location The location to write       */ -    private static void WriteWorld(String path, @NotNull Location location) { - +    private static void writeWorld(String path, @NotNull Location location) {          ConfigurationSection section = config.getConfigurationSection(path);          if (section == null) { diff --git a/src/main/java/com/MylesAndMore/Tumble/config/ConfigManager.java b/src/main/java/com/MylesAndMore/Tumble/config/ConfigManager.java index 59d653a..c279a22 100644 --- a/src/main/java/com/MylesAndMore/Tumble/config/ConfigManager.java +++ b/src/main/java/com/MylesAndMore/Tumble/config/ConfigManager.java @@ -11,7 +11,8 @@ import static com.MylesAndMore.Tumble.Main.plugin;   * Manages config.yml and stores its options   */  public class ConfigManager { -    public static boolean HideLeaveJoin; +    public static boolean hideLeaveJoin; +    public static boolean hideDeathMessages;      public static int waitDuration;      private static Configuration config; @@ -25,8 +26,10 @@ public class ConfigManager {          configYml.saveDefaultConfig();          config = configYml.getConfig();          defaultConfig = Objects.requireNonNull(config.getDefaults()); -        HideLeaveJoin = config.getBoolean("hide-join-leave-messages", false); +        hideLeaveJoin = config.getBoolean("hide-join-leave-messages", false); +        hideDeathMessages = config.getBoolean("hide-death-messages", false);          waitDuration = config.getInt("wait-duration", 15); +          validate();      } diff --git a/src/main/java/com/MylesAndMore/Tumble/game/Arena.java b/src/main/java/com/MylesAndMore/Tumble/game/Arena.java index 71849e6..157c59c 100644 --- a/src/main/java/com/MylesAndMore/Tumble/game/Arena.java +++ b/src/main/java/com/MylesAndMore/Tumble/game/Arena.java @@ -1,7 +1,6 @@  package com.MylesAndMore.Tumble.game;  import org.bukkit.Location; -import org.bukkit.World;  import org.jetbrains.annotations.NotNull;  /** diff --git a/src/main/java/com/MylesAndMore/Tumble/game/EventListener.java b/src/main/java/com/MylesAndMore/Tumble/game/EventListener.java index 9f1456e..0b23779 100644 --- a/src/main/java/com/MylesAndMore/Tumble/game/EventListener.java +++ b/src/main/java/com/MylesAndMore/Tumble/game/EventListener.java @@ -26,10 +26,10 @@ import java.util.Objects;  import static com.MylesAndMore.Tumble.Main.plugin;  /** - * An event listener for a game of tumble. + * An event listener for a game of Tumble.   */  public class EventListener implements Listener { -    Game game; +    final Game game;      /**       * Create a new EventListener for a game. @@ -43,7 +43,7 @@ public class EventListener implements Listener {      @EventHandler      public void PlayerJoinEvent(PlayerJoinEvent event) {          // Hide/show join message accordingly -        if (ConfigManager.HideLeaveJoin) { +        if (event.getPlayer().getWorld() == game.arena.gameSpawn.getWorld() && ConfigManager.hideLeaveJoin) {              event.setJoinMessage(null);          }      } @@ -51,11 +51,11 @@ public class EventListener implements Listener {      @EventHandler      public void PlayerQuitEvent(PlayerQuitEvent event) {          // Hide/show leave message accordingly -        if (ConfigManager.HideLeaveJoin) { +        if (event.getPlayer().getWorld() == game.arena.gameSpawn.getWorld() && ConfigManager.hideLeaveJoin) {              event.setQuitMessage(null);          } -        // remove player from game if they leave during a game +        // Remove player from game if they leave during a game          if (game.gamePlayers.contains(event.getPlayer())) {              game.removePlayer(event.getPlayer());          } @@ -63,7 +63,12 @@ public class EventListener implements Listener {      @EventHandler      public void PlayerDeathEvent(PlayerDeathEvent event) { -        // inform the game that the player died and respawn them +        // Hide death messages if configured +        if (event.getEntity().getWorld() == game.arena.gameSpawn.getWorld() && ConfigManager.hideDeathMessages) { +            event.setDeathMessage(null); +        } + +        // Inform the game that the player died and respawn them          if (game.gamePlayers.contains(event.getEntity()) && game.gameState == GameState.RUNNING) {              game.playerDeath(event.getEntity());              Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> event.getEntity().spigot().respawn(), 10); @@ -109,8 +114,7 @@ public class EventListener implements Listener {                              event.getHitBlock().getType());                      event.getHitBlock().setType(Material.AIR);                  } -            } -            else if (event.getHitEntity() != null) { +            } else if (event.getHitEntity() != null) {                  if (event.getHitEntity() instanceof Player hitPlayer) {                      // Also cancel any knockback                      Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> hitPlayer.setVelocity(new Vector())); @@ -134,7 +138,7 @@ public class EventListener implements Listener {          if (Objects.equals(game.gameState, GameState.STARTING) && !equalPosition(event.getFrom(),event.getTo())) {              event.setCancelled(true);          } -        // kill player if they are below a Y level +        // Kill player if they are below configured Y level          if (game.arena.killAtY != null && game.gameState == GameState.RUNNING) {              if (event.getPlayer().getLocation().getY() <= game.arena.killAtY) {                  event.getPlayer().setHealth(0); @@ -204,7 +208,7 @@ public class EventListener implements Listener {      }      @EventHandler -    public void PlayerRespwanEvent(PlayerRespawnEvent event) { +    public void PlayerRespawnEvent(PlayerRespawnEvent event) {          // Make sure players respawn in the correct location          if (game.gamePlayers.contains(event.getPlayer())) {              event.setRespawnLocation(game.arena.gameSpawn); @@ -226,5 +230,4 @@ public class EventListener implements Listener {                  (l1.getY() == l2.getY()) &&                  (l1.getZ() == l2.getZ());      } -  }
\ No newline at end of file diff --git a/src/main/java/com/MylesAndMore/Tumble/game/Game.java b/src/main/java/com/MylesAndMore/Tumble/game/Game.java index e9b7223..b309d42 100644 --- a/src/main/java/com/MylesAndMore/Tumble/game/Game.java +++ b/src/main/java/com/MylesAndMore/Tumble/game/Game.java @@ -48,7 +48,7 @@ public class Game {      }      /** -     * Adds a player to the wait area. Called from /tmbl join +     * Adds a player to the wait area. Called from /tumble join       * Precondition: the game is in state WAITING       * @param p Player to add       */ @@ -62,15 +62,14 @@ public class Game {          }          if (gamePlayers.size() >= 2 && gameState == GameState.WAITING) {              autoStart(); -        } -        else { +        } else {              displayActionbar(Collections.singletonList(p), LanguageManager.fromKeyNoPrefix("waiting-for-players"));          }      }      /**       * Starts the game -     * Called from /tmbl forceStart or after the wait counter finishes +     * Called from /tumble forceStart or after the wait counter finishes       */      public void gameStart() { @@ -79,15 +78,15 @@ public class Game {              return;          } -        // cancel wait timer +        // Cancel wait timer          Bukkit.getServer().getScheduler().cancelTask(autoStartID);          autoStartID = -1; -        // register event listener +        // Register event listener          eventListener = new EventListener(this);          Bukkit.getServer().getPluginManager().registerEvents(eventListener, plugin); -        // save inventories (if not already done) +        // Save inventories (if not already done)          for (Player p : gamePlayers) {              if (!inventories.containsKey(p)) {                  inventories.put(p, p.getInventory().getContents()); @@ -107,22 +106,18 @@ public class Game {          scatterPlayers(gamePlayers);          // Put all players in spectator to prevent them from getting kicked for flying          setGamemode(gamePlayers, GameMode.SPECTATOR); -        // do it again in case they were not in the world yet -        Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> { -            setGamemode(gamePlayers, GameMode.SPECTATOR); -        }, 10); +        // Do it again in a bit in case they were not in the world yet +        Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> setGamemode(gamePlayers, GameMode.SPECTATOR), 10);          clearInventories(gamePlayers);          clearArena();          prepareGameType(type);          // Begin the countdown sequence -        Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> { -            countdown(() -> { -                setGamemode(gamePlayers, GameMode.SURVIVAL); -                gameState = GameState.RUNNING; -            }); -        }, 100); +        Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> countdown(() -> { +            setGamemode(gamePlayers, GameMode.SURVIVAL); +            gameState = GameState.RUNNING; +        }), 100);      }      /** @@ -140,7 +135,7 @@ public class Game {                  giveItems(gamePlayers, 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 +                // Also add 160t because of the countdown                  gameID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> {                      clearInventories(gamePlayers);                      giveItems(gamePlayers, new ItemStack(Material.SNOWBALL)); @@ -191,13 +186,11 @@ public class Game {              if (gameWins.get(winner) == 3) {                  gameEnd(); -            } -            else { // If that player doesn't have three wins, nobody else does, so we need another round +            } else { // If that player doesn't have three wins, nobody else does, so we need another round                  displayTitles(gamePlayers, LanguageManager.fromKeyNoPrefix("round-over"), LanguageManager.fromKeyNoPrefix("round-winner").replace("%winner%", winner.getDisplayName()), 5, 60, 5);                  Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, this::roundStart, 100);              } -        } -        else { +        } else {              displayTitles(gamePlayers, LanguageManager.fromKeyNoPrefix("round-over"), LanguageManager.fromKeyNoPrefix("round-draw"), 5, 60, 5);              Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, this::roundStart, 100);          } @@ -207,40 +200,24 @@ public class Game {       * Ends game: Displays overall winner and teleports players to lobby       */      private void gameEnd() { -          if (!gamePlayers.isEmpty()) {              setGamemode(gamePlayers, GameMode.SPECTATOR);              clearInventories(gamePlayers); -            // display winner +            // Display winner              Player winner = getPlayerWithMostWins(gameWins);              if (winner != null) {                  displayTitles(gamePlayers, LanguageManager.fromKeyNoPrefix("game-over"), LanguageManager.fromKeyNoPrefix("game-winner").replace("%winner%",winner.getDisplayName()), 5, 60, 5);              }              displayActionbar(gamePlayers, LanguageManager.fromKeyNoPrefix("lobby-in-10")); - -            // Wait 10s (200t), then +            // Wait 10s (200t), then clear the arena and teleport players back              Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> {                  clearArena(); - -                // teleport player back and restore inventory                  for (Player p : gamePlayers) { -                    p.getInventory().clear(); -                    p.setGameMode(GameMode.SURVIVAL); -                    if (p == winner && arena.winnerLobby != null) { -                        p.teleport(arena.winnerLobby); -                    } -                    else { -                        p.teleport(Objects.requireNonNull(arena.lobby)); -                    } - -                    if (inventories.containsKey(p)) { -                        p.getInventory().setContents(inventories.get(p)); -                    } +                    sendToLobby(p, p == winner);                  } -              }, 200);          } @@ -254,10 +231,12 @@ public class Game {      /**       * Stops the game, usually while it is still going -     * called if too many players leave, or from /tmbl forceStop +     * Called if too many players leave, or from /tumble forceStop       */      public void stopGame() { -        gamePlayers.forEach(this::removePlayer); +        // A new list must be created to avoid removing elements while iterating +        List<Player> players = new ArrayList<>(gamePlayers); +        players.forEach(this::removePlayer);          Bukkit.getServer().getScheduler().cancelTask(gameID);          gameID = -1; @@ -275,50 +254,34 @@ public class Game {      public void removePlayer(Player p) {          gamePlayers.remove(p); -        // check if the game has not started yet +        // Check if the game has not started yet          if (gameState == GameState.WAITING) { - -            // inform player that there are no longer enough players to start +            // Inform player that there are no longer enough players to start              if (gamePlayers.size() < 2) {                  displayActionbar(gamePlayers, LanguageManager.fromKeyNoPrefix("waiting-for-players"));              } -            // teleport player back and restore inventory -            if (arena.waitArea != null) { -                p.getInventory().clear(); -                p.setGameMode(GameMode.SURVIVAL); -                p.teleport(arena.lobby); -                if (inventories.containsKey(p)) { -                    p.getInventory().setContents(inventories.get(p)); -                } -            } -        } -        else { -            // stop the game if there are not enough players +            sendToLobby(p, false); +        } else { +            // Stop the game if there are no longer enough players              if (gamePlayers.size() < 2) {                  stopGame();              } -            // teleport player back and restore inventory -            p.getInventory().clear(); -            p.setGameMode(GameMode.SURVIVAL); -            p.teleport(arena.lobby); -            if (inventories.containsKey(p)) { -                p.getInventory().setContents(inventories.get(p)); -            } +            sendToLobby(p, false); // You can never win if you quit, remember that kids!!          }      }      /** -     * Initiates an automatic start of a Tumble game +     * Attempts to initiate an automatic start of a Tumble game       */      public void autoStart() { -        // Wait for the player to load in          int waitDuration = ConfigManager.waitDuration; +        if (waitDuration <= 0) { return; }          Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> {              displayActionbar(gamePlayers, LanguageManager.fromKeyNoPrefix("time-till-start").replace("%wait%",waitDuration+""));              playSound(gamePlayers, Sound.BLOCK_NOTE_BLOCK_CHIME, SoundCategory.BLOCKS, 1, 1); -            // Schedule a process to start the game in 300t (15s) and save the PID so we can cancel it later if needed +            // Schedule a process to start the game in the specified waitDuration and save the PID so we can cancel it later if needed              autoStartID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, this::gameStart, waitDuration * 20L);          }, 50);      } @@ -329,7 +292,7 @@ public class Game {       */      public void playerDeath(Player player) {          player.setGameMode(GameMode.SPECTATOR); -        // remove that player (who just died) from the roundPlayersArray, effectively eliminating them, +        // Remove that player (who just died) from the alive players, effectively eliminating them,          playersAlive.remove(player);          // If there are less than 2 players in the game (1 just died),          if (playersAlive.size() < 2 && gameState == GameState.RUNNING) { @@ -337,7 +300,7 @@ public class Game {          }      } -    // utility functions +    // -- Utility functions --      /**       * Teleports a list of players to the specified scatter locations in the gameWorld @@ -482,4 +445,27 @@ public class Game {                  new Location(gameSpawn.getWorld(), gameSpawn.getX() + 20, gameSpawn.getY(), gameSpawn.getZ() + 20),                  Material.AIR);      } + +    /** +     * Teleports a player to the lobby and restores their inventory +     * @param p Player to teleport +     * @param winner Whether the player is the winner +     */ +    private void sendToLobby(Player p, boolean winner) { +        p.getInventory().clear(); +        p.setGameMode(GameMode.SURVIVAL); +        if (winner && arena.winnerLobby != null) { +            p.teleport(arena.winnerLobby); +        } else { +            // Use default world spawn if lobby is not set +            if (arena.lobby == null) { +                p.teleport(Objects.requireNonNull(Bukkit.getWorlds().get(0)).getSpawnLocation()); +            } else { +                p.teleport(Objects.requireNonNull(arena.lobby)); +            } +        } +        if (inventories.containsKey(p)) { +            p.getInventory().setContents(inventories.get(p)); +        } +    }  } diff --git a/src/main/java/com/MylesAndMore/Tumble/game/Generator.java b/src/main/java/com/MylesAndMore/Tumble/game/Generator.java index 2ef0957..dac0162 100644 --- a/src/main/java/com/MylesAndMore/Tumble/game/Generator.java +++ b/src/main/java/com/MylesAndMore/Tumble/game/Generator.java @@ -7,6 +7,8 @@ import org.bukkit.block.BlockFace;  import java.util.*; +// TODO: clean up generator (when layers refactor is done) +  /**   * Holds the methods that generate blocks in-game such as cylinders, cuboids, and block clumps.   */ @@ -23,31 +25,28 @@ public class Generator {          // 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), LayerManager.getRandom()); -        } -        else if (random.nextInt(4) == 1) { +            Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.AIR), LayerManager.getRandom()); +        } 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), LayerManager.getRandom()); -        } -        else if (random.nextInt(4) == 2) { +            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.AIR), LayerManager.getRandom()); +        } else if (random.nextInt(4) == 2) {              // Multi-tiered circle -            Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.SNOW_BLOCK), LayerManager.getRandom()); +            Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.AIR), LayerManager.getRandom());              Generator.generateLayer(layer, 13, 1, Material.AIR);              layer.setY(layer.getY() - 1); -            Generator.generateClumps(Generator.generateLayer(layer, 13, 1, Material.GRASS_BLOCK), LayerManager.getRandom()); +            Generator.generateClumps(Generator.generateLayer(layer, 13, 1, Material.AIR), LayerManager.getRandom());              Generator.generateLayer(layer, 4, 1, Material.AIR);              layer.setY(layer.getY() - 1); -            Generator.generateClumps(Generator.generateLayer(layer, 4, 1, Material.PODZOL), LayerManager.getRandom()); -        } -        else { +            Generator.generateClumps(Generator.generateLayer(layer, 4, 1, Material.AIR), LayerManager.getRandom()); +        } 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), LayerManager.getRandom()); +            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.AIR), LayerManager.getRandom());              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), LayerManager.getRandom()); +            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.AIR), LayerManager.getRandom());              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), LayerManager.getRandom()); +            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.AIR), LayerManager.getRandom());          }      } @@ -57,80 +56,78 @@ public class Generator {       */      public static void generateLayersSnowballs(Location layer) {          Random random = new Random(); +        Layers layers = new Layers();          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), LayerManager.getRandom()); +            Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.AIR), LayerManager.getRandom());              layer.setY(layer.getY() - 6); -            Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.STONE), LayerManager.getRandom()); +            Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.AIR), LayerManager.getRandom());              layer.setY(layer.getY() - 6); -            Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.STONE), LayerManager.getRandom()); -        } -        else if (random.nextInt(4) == 1) { +            Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.AIR), LayerManager.getRandom()); +        } 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), LayerManager.getRandom()); +            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.AIR), LayerManager.getRandom());              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), LayerManager.getRandom()); +            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.AIR), LayerManager.getRandom());              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), LayerManager.getRandom()); -        } -        else if (random.nextInt(4) == 2) { +            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.AIR), LayerManager.getRandom()); +        } else if (random.nextInt(4) == 2) {              // Multi-tiered circle -            Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.STONE), LayerManager.getRandom()); +            Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.AIR), LayerManager.getRandom());              Generator.generateLayer(layer, 13, 1, Material.AIR);              layer.setY(layer.getY() - 1); -            Generator.generateClumps(Generator.generateLayer(layer, 13, 1, Material.GRANITE), LayerManager.getRandom()); +            Generator.generateClumps(Generator.generateLayer(layer, 13, 1, Material.AIR), LayerManager.getRandom());              Generator.generateLayer(layer, 4, 1, Material.AIR);              layer.setY(layer.getY() - 1); -            Generator.generateClumps(Generator.generateLayer(layer, 4, 1, Material.LIME_GLAZED_TERRACOTTA), LayerManager.getRandom()); +            Generator.generateClumps(Generator.generateLayer(layer, 4, 1, Material.AIR), LayerManager.getRandom());              layer.setY(layer.getY() - 6); -            Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.STONE), LayerManager.getRandom()); +            Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.AIR), LayerManager.getRandom());              Generator.generateLayer(layer, 13, 1, Material.AIR);              layer.setY(layer.getY() - 1); -            Generator.generateClumps(Generator.generateLayer(layer, 13, 1, Material.GRANITE), LayerManager.getRandom()); +            Generator.generateClumps(Generator.generateLayer(layer, 13, 1, Material.AIR), LayerManager.getRandom());              Generator.generateLayer(layer, 4, 1, Material.AIR);              layer.setY(layer.getY() - 1); -            Generator.generateClumps(Generator.generateLayer(layer, 4, 1, Material.LIME_GLAZED_TERRACOTTA), LayerManager.getRandom()); +            Generator.generateClumps(Generator.generateLayer(layer, 4, 1, Material.AIR), LayerManager.getRandom());              layer.setY(layer.getY() - 6); -            Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.STONE), LayerManager.getRandom()); +            Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.AIR), LayerManager.getRandom());              Generator.generateLayer(layer, 13, 1, Material.AIR);              layer.setY(layer.getY() - 1); -            Generator.generateClumps(Generator.generateLayer(layer, 13, 1, Material.GRANITE), LayerManager.getRandom()); +            Generator.generateClumps(Generator.generateLayer(layer, 13, 1, Material.AIR), LayerManager.getRandom());              Generator.generateLayer(layer, 4, 1, Material.AIR);              layer.setY(layer.getY() - 1); -            Generator.generateClumps(Generator.generateLayer(layer, 4, 1, Material.LIME_GLAZED_TERRACOTTA), LayerManager.getRandom()); -        } -        else { +            Generator.generateClumps(Generator.generateLayer(layer, 4, 1, Material.AIR), LayerManager.getRandom()); +        } 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), LayerManager.getRandom()); +            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.AIR), LayerManager.getRandom());              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), LayerManager.getRandom()); +            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.AIR), LayerManager.getRandom());              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), LayerManager.getRandom()); +            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.AIR), LayerManager.getRandom());              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), LayerManager.getRandom()); +            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.AIR), LayerManager.getRandom());              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), LayerManager.getRandom()); +            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.AIR), LayerManager.getRandom());              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), LayerManager.getRandom()); +            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.AIR), LayerManager.getRandom());              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), LayerManager.getRandom()); +            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.AIR), LayerManager.getRandom());              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), LayerManager.getRandom()); +            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.AIR), LayerManager.getRandom());              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), LayerManager.getRandom()); +            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.AIR), LayerManager.getRandom());          }      } diff --git a/src/main/java/com/MylesAndMore/Tumble/plugin/GameState.java b/src/main/java/com/MylesAndMore/Tumble/plugin/GameState.java index 06b2abe..e27c728 100644 --- a/src/main/java/com/MylesAndMore/Tumble/plugin/GameState.java +++ b/src/main/java/com/MylesAndMore/Tumble/plugin/GameState.java @@ -4,5 +4,5 @@ public enum GameState {      WAITING,      STARTING,      RUNNING, -    ENDING +    ENDING,  } diff --git a/src/main/resources/arenas.yml b/src/main/resources/arenas.yml index 3b755c3..7c26e08 100644 --- a/src/main/resources/arenas.yml +++ b/src/main/resources/arenas.yml @@ -1,2 +1,2 @@ -# NOTE: Coordinates cannot be zero! Use something like 0.5 -arenas: {}
\ No newline at end of file +# NOTE: No coordinate can be equal to zero! Use 0.5 instead if needed. +arenas: diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index ded50ef..28cc4e2 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,7 +1,9 @@ -# Hides player join/leave messages in public chat +# Hides player join and leave messages in public chat during games  hide-join-leave-messages: false -# Duration in seconds to wait for more players to join -wait-duration: 15 - +# Hides player death messages in public chat during games +hide-death-messages: false +# Duration (in seconds) to wait for more players to join a game before starting +# Set to 0 to disable +wait-duration: 15 diff --git a/src/main/resources/language.yml b/src/main/resources/language.yml index 835d577..388c975 100644 --- a/src/main/resources/language.yml +++ b/src/main/resources/language.yml @@ -1,32 +1,36 @@ +# All plugin chat messages will have this message prepended to them  prefix: "&f[&eTumble&f] " -unknown-command: "&4Unknown command '%command%'" -no-permission: "&4You do not have permission to perform this command! &7Required permission: '%permission%.'" -missing-arena-parameter: "&4Missing arena name!" -invalid-arena: "&4arena '%arena%' does not exist!" -invalid-type: "&4Invalid game type!" -no-game-in-arena: "&4No game is currently running in this arena!" -player-not-in-game: "&4You are not in a game!" -not-for-console: "&4This cannot be run by the console!" -game-in-progress: "&4This game is still in progress!&7 wait until it finishes or join another game." -another-type-in-arena: "A game of %type% is currently taking place in this arena!&7 choose another arena or join it with '/tmbl join %arena% %type%'." -already-in-game: "&4You are already in a game! Leave it to join another one." -arena-not-ready: "&4This arena is not finished being set up!" -arena-not-ready-op: "&4Incomplete arena. &7Set a game spawn with '/tmbl setGameSpawn'." -specify-game-type: "&4No game is currently taking place in this arena! &7Provide the game type to start one." - -create-success: "&aArena created successfully! &eBefore you can join, you must set a game spawn location with '/tmbl setgamespawn'." -forcestart-success: "&aStarting game." +# Error messages +unknown-command: "&cUnknown command '%command%'" +no-permission: "&cYou do not have permission to perform this command! &7Required permission: '%permission%.'" +missing-arena-parameter: "&cMissing arena name!" +invalid-arena: "&carena '%arena%' does not exist!" +invalid-type: "&cInvalid game type!" +no-game-in-arena: "&cNo game is currently running in this arena!" +player-not-in-game: "&cYou are not in a game!" +not-for-console: "&cThis cannot be run by the console!" +game-in-progress: "&cThis game is still in progress!&7 wait until it finishes or join another game." +another-type-in-arena: "A game of %type% is currently taking place in this arena!&7 choose another arena or join it with '/tumble join %arena% %type%'." +already-in-game: "&cYou are already in a game! Leave it to join another one." +arena-not-ready: "&cThis arena is not yet set up!" +arena-not-ready-op: "&cIncomplete arena. &7Set a game spawn with '/tumble setGameSpawn'." +specify-game-type: "&cNo game is currently taking place in this arena! &7Provide the game type to start one." + +# Success messages +create-success: "&aArena created successfully! &eBefore this arena is usable, you must set a game spawn location with '/tumble setgamespawn'." +forcestart-success: "&aStarting game..."  forcestop-success: "&aGame stopped."  join-success: "&aJoined game &d%arena% - %type%"  leave-success: "&aLeft game &d%arena% - %type%" -reload-success: "&aConfig files reloaded. &eCheck console for errors." +reload-success: "&aConfig files reloaded. &eCheck console for possible errors."  remove-success: "&aArena removed."  set-success: "&aLocation set." +# Game messages  showdown: "&4Showdown!"  lobby-in-10: "&9Returning to lobby in ten seconds..." -waiting-for-players: "&aWaiting for players" +waiting-for-players: "&aWaiting for players..."  time-till-start: "&aGame will begin in %wait% seconds!"  round-over: "&cRound over!"  round-winner: "&6%winner%  has won the round!" @@ -37,9 +41,3 @@ count-3: "&23"  count-2: "&e2"  count-1: "&41"  count-go: "&aGo!" - - - - - - diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index c8085b8..da7f8bd 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@  main: com.MylesAndMore.Tumble.Main  name: Tumble -version: 1.0.4 +version: 2.0.0  description: 'A Minecraft: Java Edition plugin recreating the Tumble minigame from Minecraft Legacy Console Edition.'  api-version: 1.16  load: POSTWORLD @@ -10,8 +10,8 @@ softdepend: [Multiverse-Core]  commands:    tumble: -    description: Base command for Rumble -    usage: "/tmbl <subCommand> ..." +    description: Base command for Tumble +    usage: "/tumble <subCommand> ..."      aliases: tmbl  permissions: @@ -22,23 +22,33 @@ permissions:      description: Allows you to leave a Tumble match.      default: true    tumble.forcestart: +    description: Allows you to forcibly start a Tumble match.      default: op    tumble.forcestop: +    description: Allows you to forcibly stop a Tumble match.      default: op    tumble.reload: +    description: Allows you to reload the Tumble configuration.      default: op    tumble.create: +    description: Allows you to create Tumble arenas.      default: op    tumble.remove: +    description: Allows you to remove Tumble arenas.      default: op    tumble.setgamespawn: +    description: Allows you to set the game spawn location for Tumble arenas.      default: op    tumble.setkillylevel: +    description: Allows you to set the kill Y-level for Tumble arenas.      default: op    tumble.setlobby: +    description: Allows you to set the lobby location for Tumble arenas.      default: op    tumble.setwaitarea: +    description: Allows you to set the wait area location for Tumble arenas.      default: op    tumble.setwinnerlobby: +    description: Allows you to set the winner lobby location for Tumble arenas.      default: op | 
