From 76abe512529541872359c04909eb2150e1a2ce80 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Thu, 1 Dec 2022 08:45:29 -0600 Subject: add todo list for @CraivMan and I --- README.md | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 02f6944..681c340 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,36 @@ -# tumble -A Minecraft: Java Edition plugin recreating the Tumble minigame from Minecraft: Xbox 360 Edition. +# tumble-alphatest (@MylesAndMore @CraivMan) + +please let me know if there is anything more you think we should add @CraivMan! +once this list is complete and all bugs are fixed, we *should* be ready for release... + +## generation + +- [ ] layers should be able to generate w/ "clumps" of blocks; instead of only one material as a whole + - [ ] the clump size should be customizable (for later); be able to set a min/max val and it will choose randomly per each clump (not in config file yet, just internally) + - PLEASE make a new class for this and make use of the generator if you can! + +## game realism + +- [ ] make the game blocks instant-breakable +- [ ] add infinite snowballs in the gamemanager for tumble mode +- [ ] make the randomized mode logic + +## game logic (fyi: very object-oriented) + +- [ ] make a Game class and object that we can initialize a new instance of with a gameType + - [ ] within this game object, while games are running: + - [ ] prevent players from joining/autojoining during + - [ ] keep track of when someone wins; start a new round when this happens + - [ ] keep track of how many wins each player has; end the game when a player reaches 3 + - [ ] add a section in the config for a place to tp the winning player + - [ ] add logic to do this + +## game legitimacy (@MylesAndMore) + +- [ ] add some example layer generation and layer material types, from actual game @MylesAndMore + +- [ ] add two configs where you can: + - [ ] set if you want the game to auto-start + - [ ] set the amt of players you want the game to auto-start at + +- [ ] add game music? but probably only for us; I feel like the og music must be copyrighted -- cgit v1.2.3 From 8d2e1c91f37caeae693fa3be2a65a89fb68eda65 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Thu, 1 Dec 2022 08:50:26 -0600 Subject: oopsies forgot important things --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 681c340..6cc688c 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,11 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele - [ ] add some example layer generation and layer material types, from actual game @MylesAndMore +## configuration/customization + - [ ] add two configs where you can: - [ ] set if you want the game to auto-start - - [ ] set the amt of players you want the game to auto-start at + - [ ] set the amt of players you want the game to auto-start at + - [ ] program the auto-start (just add an if statement on the PlayerJoin listener to run the StartGame method on a certain amt of players in the config) - [ ] add game music? but probably only for us; I feel like the og music must be copyrighted -- cgit v1.2.3 From f4fec2cc9645cc85197d3c78916b459adf0d0d1a Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Thu, 1 Dec 2022 10:45:10 -0600 Subject: I would never --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 6cc688c..05bfa0f 100644 --- a/README.md +++ b/README.md @@ -36,4 +36,6 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele - [ ] set the amt of players you want the game to auto-start at - [ ] program the auto-start (just add an if statement on the PlayerJoin listener to run the StartGame method on a certain amt of players in the config) +## etc + - [ ] add game music? but probably only for us; I feel like the og music must be copyrighted -- cgit v1.2.3 From 37dc2987244297ad2fe0029d964a19854d68c002 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Thu, 1 Dec 2022 14:30:24 -0600 Subject: start on methodized game --- src/main/java/com/MylesAndMore/tumble/GameManager.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/MylesAndMore/tumble/GameManager.java b/src/main/java/com/MylesAndMore/tumble/GameManager.java index a778c7d..07eb3f9 100644 --- a/src/main/java/com/MylesAndMore/tumble/GameManager.java +++ b/src/main/java/com/MylesAndMore/tumble/GameManager.java @@ -11,6 +11,13 @@ import java.util.List; import java.util.Objects; public class GameManager { + public boolean TumbleGame(String gameType) { + // Run createGame to distribute items + // Make a method to generate random layers (so we can reuse it later) + // Run sendWorld (move from startGame) + // Start blocking new games and start keeping score/rounds + } + public static boolean createGame(String gameType) { if (Objects.equals(gameType, "shovels")) { // Generate layers -- cgit v1.2.3 From 12cbc14f647e9707d855dc5523a8d28c6c95d892 Mon Sep 17 00:00:00 2001 From: Myles Date: Thu, 1 Dec 2022 19:20:27 -0600 Subject: return statements exist? --- src/main/java/com/MylesAndMore/tumble/GameManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/MylesAndMore/tumble/GameManager.java b/src/main/java/com/MylesAndMore/tumble/GameManager.java index 07eb3f9..a00d764 100644 --- a/src/main/java/com/MylesAndMore/tumble/GameManager.java +++ b/src/main/java/com/MylesAndMore/tumble/GameManager.java @@ -16,6 +16,7 @@ public class GameManager { // Make a method to generate random layers (so we can reuse it later) // Run sendWorld (move from startGame) // Start blocking new games and start keeping score/rounds + return true; } public static boolean createGame(String gameType) { -- cgit v1.2.3 From c4fc5e933f3651dd4ee9431d19bb70f3eef5abb8 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Fri, 2 Dec 2022 14:37:53 -0600 Subject: begin the game object (eventual replacement for gamemanager) also added another field in the TumbleManager for getting the game type --- src/main/java/com/MylesAndMore/tumble/Game.java | 99 ++++++++++++++++++++++ .../com/MylesAndMore/tumble/TumbleManager.java | 1 + 2 files changed, 100 insertions(+) create mode 100644 src/main/java/com/MylesAndMore/tumble/Game.java 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..dcc3a78 --- /dev/null +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -0,0 +1,99 @@ +package com.MylesAndMore.tumble; + +import com.MylesAndMore.tuble.TumbleManager; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.Location; +import org.bukkit.World; + +import Java.util.Arrays; +import Java.util.Collections; +import Java.util.List; + +public final class Game { + // Define the gameInstnace + private static Game gameInstance; + + // Private Game() constructor for singleton instance + private Game() { } + + // Other priate methods for getters and setters go here + + // Define local game vars + // The gameType keeps the current game type (shocker) + String gameType = null; + + // Creates a new Game + // This will return true if the game succeeds creation, and false if not + private static boolean createGame() { + if (Objects.equals(TumbleManager.getGameType(), "shovels")) { + // shovels logic + gameType = "shovels" + } + else if (Objects.equals(TumbleManager.getGameType(), "snowballs")) { + // snowballs + gameType = "snowballs" + } + else if (Objects.equals(TumbleManager.getGameType(), "mixed")) { + // mixed (choose random shovels or snowballs) + gameType = "mixed" + } + else { + // The game type in the config did not match a specified game type; return false to signify that + return false; + } + return true; + } + + private static boolean sendPlayers() { + World gameWorld = Bukkit.getWorld(TumbleManager.getGameWorld()); + // Define the game world's spawnpoint as a new Location + Location gameSpawn = new Location(gameWorld.getSpawnLocation()); + // Get the X, Y, and Z coords of that location + Location x = gameSpawn.getX(); + Location y = gameSpawn.getY(); + Location z = gameSpawn.getZ(); + // Create Locations to scatter players around the first layer + // These are just edited off the original spawn location; + // they assume that the first layer has a radius of 17 blocks (it always will w/ the current generator code) + List scatterLocations = Arrays.asList( + new Location(gameWorld, (x - 16), y, z); + new Location(gameWorld, x, y, (z - 16)); + new Location(gameWorld, (x + 16), y, z);; + new Location(gameWorld, x, y, (z + 16)) + ); + // Shuffle the location list so players don't always spawn in the same location (basically, actually scatter the locations) + Collections.shuffle(scatterLocations); + // 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 playersInLobby = TumbleManager.getPlayersInLobby(); playersInLobby.size() > 0; playersInLobby = TumbleManager.getPlayersInLobby() & scatterLoations.remove(0)) { + // Get a singular player from the player list + Player aPlayer = playersInLobby.get(0); + // Get a singular location from the scatter list + Location aLocation = scatterLoations.get(0); + // Teleport that player to that scatter location + aPlayer.teleport(aLocation); + } + + // 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 + } + + + + // Public method to get the game instance (singleton logic) + public static Game getGame() { + if (gameInstance == null) { + gameInstance = new Game(); + } + return gameInstance; + } + + // Public method to get the game type + // This is public because you aren't modifying the game, just getting its type, so there shouldn't be any conflicts + public static String getGameType() { + return gameType; + } +} \ 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..aeecd44 100644 --- a/src/main/java/com/MylesAndMore/tumble/TumbleManager.java +++ b/src/main/java/com/MylesAndMore/tumble/TumbleManager.java @@ -18,6 +18,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("gameType") } public static List getPlayersInGame() { return Bukkit.getServer().getWorld(TumbleManager.getGameWorld()).getPlayers(); } public static List getPlayersInLobby() { return Bukkit.getServer().getWorld(TumbleManager.getLobbyWorld()).getPlayers(); } -- cgit v1.2.3 From fc6d55c3fcdc23c841d0e61f1e9f46b04a815c95 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Fri, 2 Dec 2022 14:48:56 -0600 Subject: VARIABLE TYPES --- src/main/java/com/MylesAndMore/tumble/Game.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index dcc3a78..6135cfd 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -50,9 +50,9 @@ public final class Game { // Define the game world's spawnpoint as a new Location Location gameSpawn = new Location(gameWorld.getSpawnLocation()); // Get the X, Y, and Z coords of that location - Location x = gameSpawn.getX(); - Location y = gameSpawn.getY(); - Location z = gameSpawn.getZ(); + int x = gameSpawn.getX(); + int y = gameSpawn.getY(); + int z = gameSpawn.getZ(); // Create Locations to scatter players around the first layer // These are just edited off the original spawn location; // they assume that the first layer has a radius of 17 blocks (it always will w/ the current generator code) -- cgit v1.2.3 From 1bd5aeeadf2449fcadcf78641f086e5d285d5bae Mon Sep 17 00:00:00 2001 From: Myles Date: Fri, 2 Dec 2022 19:27:54 -0600 Subject: I CANT DO THIS by that I mean editing without an ide seriously the chromebook is AWFUL :(((( --- src/main/java/com/MylesAndMore/tumble/Game.java | 42 ++++++++++++------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 6135cfd..2161e2f 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -1,17 +1,18 @@ package com.MylesAndMore.tumble; -import com.MylesAndMore.tuble.TumbleManager; +import com.MylesAndMore.tumble.TumbleManager; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.Location; import org.bukkit.World; -import Java.util.Arrays; -import Java.util.Collections; -import Java.util.List; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; public final class Game { - // Define the gameInstnace + // Define the gameInstance private static Game gameInstance; // Private Game() constructor for singleton instance @@ -21,22 +22,22 @@ public final class Game { // Define local game vars // The gameType keeps the current game type (shocker) - String gameType = null; + static String gameType = null; // Creates a new Game // This will return true if the game succeeds creation, and false if not private static boolean createGame() { if (Objects.equals(TumbleManager.getGameType(), "shovels")) { // shovels logic - gameType = "shovels" + gameType = "shovels"; } else if (Objects.equals(TumbleManager.getGameType(), "snowballs")) { // snowballs - gameType = "snowballs" + gameType = "snowballs"; } else if (Objects.equals(TumbleManager.getGameType(), "mixed")) { // mixed (choose random shovels or snowballs) - gameType = "mixed" + gameType = "mixed"; } else { // The game type in the config did not match a specified game type; return false to signify that @@ -45,32 +46,31 @@ public final class Game { return true; } - private static boolean sendPlayers() { + private static void sendPlayers() { World gameWorld = Bukkit.getWorld(TumbleManager.getGameWorld()); // Define the game world's spawnpoint as a new Location - Location gameSpawn = new Location(gameWorld.getSpawnLocation()); + Location gameSpawn = gameWorld.getSpawnLocation(); // Get the X, Y, and Z coords of that location - int x = gameSpawn.getX(); - int y = gameSpawn.getY(); - int z = gameSpawn.getZ(); + double x = gameSpawn.getX(); + double y = gameSpawn.getY(); + double z = gameSpawn.getZ(); // Create Locations to scatter players around the first layer // These are just edited off the original spawn location; // they assume that the first layer has a radius of 17 blocks (it always will w/ the current generator code) List scatterLocations = Arrays.asList( - new Location(gameWorld, (x - 16), y, z); - new Location(gameWorld, x, y, (z - 16)); - new Location(gameWorld, (x + 16), y, z);; - new Location(gameWorld, x, y, (z + 16)) - ); + new Location(gameWorld, (x - 16), y, z), + new Location(gameWorld, x, y, (z - 16)), + new Location(gameWorld, (x + 16), y, z), + new Location(gameWorld, x, y, (z + 16))); // Shuffle the location list so players don't always spawn in the same location (basically, actually scatter the locations) Collections.shuffle(scatterLocations); // 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 playersInLobby = TumbleManager.getPlayersInLobby(); playersInLobby.size() > 0; playersInLobby = TumbleManager.getPlayersInLobby() & scatterLoations.remove(0)) { + for (List playersInLobby = TumbleManager.getPlayersInLobby(); playersInLobby.size() > 0; playersInLobby = TumbleManager.getPlayersInLobby(), scatterLocations.remove(0)) { // Get a singular player from the player list Player aPlayer = playersInLobby.get(0); // Get a singular location from the scatter list - Location aLocation = scatterLoations.get(0); + Location aLocation = scatterLocations.get(0); // Teleport that player to that scatter location aPlayer.teleport(aLocation); } -- cgit v1.2.3 From 19a24e3adc4b2117b68acdf3aad006349d79542a Mon Sep 17 00:00:00 2001 From: Myles Date: Fri, 2 Dec 2022 19:28:50 -0600 Subject: imagine spelling --- src/main/java/com/MylesAndMore/tumble/Game.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 2161e2f..0f54021 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -1,6 +1,5 @@ package com.MylesAndMore.tumble; -import com.MylesAndMore.tumble.TumbleManager; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.Location; @@ -18,7 +17,7 @@ public final class Game { // Private Game() constructor for singleton instance private Game() { } - // Other priate methods for getters and setters go here + // Other private methods for getters and setters go here // Define local game vars // The gameType keeps the current game type (shocker) @@ -82,7 +81,6 @@ public final class Game { } - // Public method to get the game instance (singleton logic) public static Game getGame() { if (gameInstance == null) { -- cgit v1.2.3 From aab494cf63eaeb931b84131f5fd7dfd680fc4f87 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Fri, 2 Dec 2022 20:30:15 -0600 Subject: update readme with new tasks --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 05bfa0f..4c64520 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,10 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele ## game realism +- [ ] make the shovel in shovels mode not lose any durabilty - [ ] make the game blocks instant-breakable - [ ] add infinite snowballs in the gamemanager for tumble mode +- [ ] make it so that you can't remove any of the game items from your inventory - [ ] make the randomized mode logic ## game logic (fyi: very object-oriented) -- cgit v1.2.3 From d3394ac7ffdfd012bf6e83f14fe04d2a48e912d2 Mon Sep 17 00:00:00 2001 From: Myles Date: Fri, 2 Dec 2022 20:34:42 -0600 Subject: I WILL MURDER EVER YSINGEL EMISCOLON IN TEH WEORLD --- src/main/java/com/MylesAndMore/tumble/TumbleManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/MylesAndMore/tumble/TumbleManager.java b/src/main/java/com/MylesAndMore/tumble/TumbleManager.java index aeecd44..4bfc275 100644 --- a/src/main/java/com/MylesAndMore/tumble/TumbleManager.java +++ b/src/main/java/com/MylesAndMore/tumble/TumbleManager.java @@ -18,7 +18,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("gameType") } + public static String getGameType() { return TumbleManager.getPlugin().getConfig().getString("gameType"); } public static List getPlayersInGame() { return Bukkit.getServer().getWorld(TumbleManager.getGameWorld()).getPlayers(); } public static List getPlayersInLobby() { return Bukkit.getServer().getWorld(TumbleManager.getLobbyWorld()).getPlayers(); } -- cgit v1.2.3 From d94f08d791031bf45a7b694472d0158b04e32b98 Mon Sep 17 00:00:00 2001 From: Myles Date: Fri, 2 Dec 2022 21:08:44 -0600 Subject: I unfourtenatly cannot spell --- src/main/java/com/MylesAndMore/tumble/TumbleManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/MylesAndMore/tumble/TumbleManager.java b/src/main/java/com/MylesAndMore/tumble/TumbleManager.java index 4bfc275..7605717 100644 --- a/src/main/java/com/MylesAndMore/tumble/TumbleManager.java +++ b/src/main/java/com/MylesAndMore/tumble/TumbleManager.java @@ -18,7 +18,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("gameType"); } + public static String getGameType() { return TumbleManager.getPlugin().getConfig().getString("gameMode"); } public static List getPlayersInGame() { return Bukkit.getServer().getWorld(TumbleManager.getGameWorld()).getPlayers(); } public static List getPlayersInLobby() { return Bukkit.getServer().getWorld(TumbleManager.getLobbyWorld()).getPlayers(); } -- cgit v1.2.3 From 934af5a9015ce6488a4d3bb7137c67c1095e9d56 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Fri, 2 Dec 2022 21:26:15 -0600 Subject: add more things to do (yay!) --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c64520..bfe1a54 100644 --- a/README.md +++ b/README.md @@ -12,10 +12,12 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele ## game realism - [ ] make the shovel in shovels mode not lose any durabilty -- [ ] make the game blocks instant-breakable +- [ ] make the game blocks breakable very fast, but **not instantly--very important for balancing!!** - [ ] add infinite snowballs in the gamemanager for tumble mode - [ ] make it so that you can't remove any of the game items from your inventory +- [ ] make snowballs actually break blocks (duh) - [ ] make the randomized mode logic +- [ ] set some limits on the spectator mode in-game; make it so they can't fly outside of the map ## game logic (fyi: very object-oriented) -- cgit v1.2.3 From d3d278fd4b26bcc2576e14ac67ef115ee084bf5d Mon Sep 17 00:00:00 2001 From: Myles Date: Fri, 2 Dec 2022 23:27:35 -0600 Subject: add init message --- src/main/java/com/MylesAndMore/tumble/Main.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/MylesAndMore/tumble/Main.java b/src/main/java/com/MylesAndMore/tumble/Main.java index 513b7d1..2a276d4 100644 --- a/src/main/java/com/MylesAndMore/tumble/Main.java +++ b/src/main/java/com/MylesAndMore/tumble/Main.java @@ -32,5 +32,8 @@ public class Main extends JavaPlugin{ 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."); } + + // Init message + Bukkit.getServer().getLogger().info("[tumble] tumble initialization complete!"); } } \ No newline at end of file -- cgit v1.2.3 From 8273f0654e8dac3ff2ce0da422afce12c54cd0e3 Mon Sep 17 00:00:00 2001 From: Myles Date: Fri, 2 Dec 2022 23:28:10 -0600 Subject: add PlayerDeathEvent for use in Game --- .../java/com/MylesAndMore/tumble/EventListener.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index 6c20a80..05f82fe 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -3,12 +3,13 @@ package com.MylesAndMore.tumble; import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; public class EventListener implements Listener{ @EventHandler - public void PlayerJoinEvent(PlayerJoinEvent event){ + 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 @@ -26,7 +27,7 @@ public class EventListener implements Listener{ } @EventHandler - public void PlayerQuitEvent(PlayerQuitEvent event){ + 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 @@ -34,4 +35,16 @@ public class EventListener implements Listener{ event.setQuitMessage(null); } } + + @EventHandler + public void PlayerDeathEvent(PlayerDeathEvent event) { + // On a PlayerDeathEvent, check to make sure the gameWorld is defined, + if (TumbleManager.getGameWorld() != null) { + // then 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()); + } + } + } } -- cgit v1.2.3 From 3a8fcb3aaec9d1c43f9d7a2f04cdbfb5b43696b3 Mon Sep 17 00:00:00 2001 From: Myles Date: Fri, 2 Dec 2022 23:29:31 -0600 Subject: new Game management GameManager.java has been superseded by Game.java this is where the game will be managed from now on; created, scores tracked, ended, etc (this was way harder than it looks to code...) AND IT STILL DOESNT WORK AOIFHJRGRI HRSDO --- src/main/java/com/MylesAndMore/tumble/Game.java | 182 ++++++++++++++++----- .../java/com/MylesAndMore/tumble/GameManager.java | 68 -------- 2 files changed, 142 insertions(+), 108 deletions(-) delete mode 100644 src/main/java/com/MylesAndMore/tumble/GameManager.java diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 0f54021..aa86e12 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -1,54 +1,132 @@ package com.MylesAndMore.tumble; -import org.bukkit.Bukkit; +import com.MylesAndMore.tumble.api.Generator; +import org.bukkit.*; import org.bukkit.entity.Player; -import org.bukkit.Location; -import org.bukkit.World; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Objects; +import java.util.*; -public final class Game { +public class Game { + // Singleton class logic // Define the gameInstance private static Game gameInstance; // Private Game() constructor for singleton instance private Game() { } - // Other private methods for getters and setters go here - + // 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 gameType keeps the current game type (shocker) - static String gameType = null; + private String gameType = null; + // The gameState keeps the current state of the game (I'm so creative, I know) + private String gameState = null; + + // Initialize a new instance of the Random class for use later + private Random Random = new Random(); + // Define the game world and its spawnpoint as a new Location for use later + private World gameWorld = Bukkit.getWorld(TumbleManager.getGameWorld()); + private Location gameSpawn = gameWorld.getSpawnLocation(); + + // Make a list of the game's players for later + private List gamePlayers = null; // Creates a new Game // This will return true if the game succeeds creation, and false if not - private static boolean createGame() { + public boolean startGame() { + gameState = "starting"; if (Objects.equals(TumbleManager.getGameType(), "shovels")) { - // shovels logic + // Set the correct gameType for the game we're playing, for later gameType = "shovels"; + // Generate the correct layers for a Shovels game + // The else statement is just in case the generator fails; this command will fail + if (generateLayers(gameType)) { + // If the layer generation succeeds, give players diamond shovels + // Reminder: we need a way for blocks to break instantly and for these to not lose durability! + giveItems(new ItemStack(Material.DIAMOND_SHOVEL)); + // Send players to the game + sendPlayers(); + // Keep in mind that after this runs, this command will complete and return true + } + else { + return false; + } } else if (Objects.equals(TumbleManager.getGameType(), "snowballs")) { - // snowballs gameType = "snowballs"; + if (generateLayers(gameType)) { + // Reminder: we need a way to make this snowball infinite! + giveItems(new ItemStack(Material.SNOWBALL)); + sendPlayers(); + } + else { + return false; + } } else if (Objects.equals(TumbleManager.getGameType(), "mixed")) { - // mixed (choose random shovels or snowballs) gameType = "mixed"; + // Mixed gamemode (choose random shovels or snowballs) + if (Random.nextInt(2) == 0) { + generateLayers("shovels"); + giveItems(new ItemStack(Material.DIAMOND_SHOVEL)); + sendPlayers(); + } + else { + generateLayers("snowballs"); + giveItems(new ItemStack(Material.SNOWBALL)); + sendPlayers(); + } } else { // The game type in the config did not match a specified game type; return false to signify that return false; } + // Update the game's players for later + gamePlayers = new ArrayList<>(TumbleManager.getPlayersInGame()); + gameState = "running"; return true; } - private static void sendPlayers() { - World gameWorld = Bukkit.getWorld(TumbleManager.getGameWorld()); - // Define the game world's spawnpoint as a new Location - Location gameSpawn = gameWorld.getSpawnLocation(); + private boolean generateLayers(String gameType) { + Location layer = gameSpawn; + if (Objects.equals(gameType, "shovels")) { + 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); + } + else if (Objects.equals(gameType, "snowballs")) { + layer.setY(layer.getY() - 1); + Generator.generateLayer(layer, 17, 1, Material.COAL_ORE); + Generator.generateLayer(layer, 13, 1, Material.AIR); + layer.setY(layer.getY() - 1); + Generator.generateLayer(layer, 13, 1, Material.GRANITE); + Generator.generateLayer(layer, 4, 1, Material.AIR); + layer.setY(layer.getY() - 1); + Generator.generateLayer(layer, 4, 1, Material.LIME_GLAZED_TERRACOTTA); + } + else { + return false; + } + return true; + } + + private void sendPlayers() { // Get the X, Y, and Z coords of that location double x = gameSpawn.getX(); double y = gameSpawn.getY(); @@ -56,42 +134,66 @@ public final class Game { // Create Locations to scatter players around the first layer // These are just edited off the original spawn location; // they assume that the first layer has a radius of 17 blocks (it always will w/ the current generator code) - List scatterLocations = Arrays.asList( - new Location(gameWorld, (x - 16), y, z), - new Location(gameWorld, x, y, (z - 16)), - new Location(gameWorld, (x + 16), y, z), - new Location(gameWorld, x, y, (z + 16))); + List scatterLocations = new ArrayList<>(); + scatterLocations.addAll(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 location list so players don't always spawn in the same location (basically, actually scatter the locations) Collections.shuffle(scatterLocations); // 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 playersInLobby = TumbleManager.getPlayersInLobby(); playersInLobby.size() > 0; playersInLobby = TumbleManager.getPlayersInLobby(), scatterLocations.remove(0)) { + for (Player aPlayer : TumbleManager.getPlayersInLobby()) { + //for (List playersInLobby = TumbleManager.getPlayersInLobby(); playersInLobby.size() > 0; playersInLobby = TumbleManager.getPlayersInLobby()) { // Get a singular player from the player list - Player aPlayer = playersInLobby.get(0); + //Player aPlayer = playersInLobby.get(0); // Get a singular location from the scatter list Location aLocation = scatterLocations.get(0); // Teleport that player to that scatter location aPlayer.teleport(aLocation); + // Remove that location from the list so that it cannot be used again + scatterLocations.remove(0); } + } - // 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 + public void playerDeath(@NotNull Player player) { + player.setGameMode(GameMode.SPECTATOR); + // If there are more than 2 players in the game, + if (gamePlayers.size() > 2) { + // remove that player (who just died) from the gamePlayersArray, effectively eliminating them, + gamePlayers.remove(player); + } + // otherwise, the game must have two people left (and one just died), meaning it is over + // This logic is so that it will not remove the last player standing from the list, so we know who the winner is. + else { + // End the game, passing the winner to the gameEnd method + gameEnd(gamePlayers.get(0)); + } } + private void gameEnd(@NotNull Player winner) { + Bukkit.getServer().broadcastMessage(ChatColor.GREEN + winner.getName() + " has won!"); + } - // Public method to get the game instance (singleton logic) - public static Game getGame() { - if (gameInstance == null) { - gameInstance = new Game(); + private void giveItems(ItemStack itemStack) { + for (List 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); } - return gameInstance; } - // Public method to get the game type - // This is public because you aren't modifying the game, just getting its type, so there shouldn't be any conflicts - public static String getGameType() { - return gameType; - } + + // Methods to get the game type and game state for other classes outside the Game + private String getGameType() { return gameType; } + + private String getGameState() { return gameState; } + } \ No newline at end of file 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 a00d764..0000000 --- a/src/main/java/com/MylesAndMore/tumble/GameManager.java +++ /dev/null @@ -1,68 +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 boolean TumbleGame(String gameType) { - // Run createGame to distribute items - // Make a method to generate random layers (so we can reuse it later) - // Run sendWorld (move from startGame) - // Start blocking new games and start keeping score/rounds - return true; - } - - 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 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); - } - } -} -- cgit v1.2.3 From 23531b7610aa1a8a10cce2a355ad0fad76d8d230 Mon Sep 17 00:00:00 2001 From: Myles Date: Fri, 2 Dec 2022 23:30:04 -0600 Subject: slight reformat in StartGame for the Game management refactors --- src/main/java/com/MylesAndMore/tumble/commands/StartGame.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java index 9daa959..df5f316 100644 --- a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java +++ b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java @@ -1,6 +1,6 @@ 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; @@ -19,7 +19,7 @@ public class StartGame implements CommandExecutor { // Check if there is a lobbyWorld specified in config if (TumbleManager.getLobbyWorld() != null) { // Check if there is more than one person in lobby - if (TumbleManager.getPlayersInLobby().size() > 1) { + if (TumbleManager.getPlayersInLobby().size() > 0) { // Check if there is a gameWorld specified in config if (TumbleManager.getGameWorld() != null) { sender.sendMessage("Checking world, this could take a few moments..."); @@ -28,12 +28,7 @@ public class StartGame implements CommandExecutor { 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(); - } - else { + if (!Game.getGame().startGame()) { // 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")); } -- cgit v1.2.3 From dfe8b42a59c4c088d53447af2eef2b71792554b9 Mon Sep 17 00:00:00 2001 From: Myles Date: Sat, 3 Dec 2022 14:12:14 -0600 Subject: slight change to start message --- src/main/java/com/MylesAndMore/tumble/commands/StartGame.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java index df5f316..aad4b9e 100644 --- a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java +++ b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java @@ -22,11 +22,10 @@ public class StartGame implements CommandExecutor { if (TumbleManager.getPlayersInLobby().size() > 0) { // Check if there is a gameWorld specified in config if (TumbleManager.getGameWorld() != null) { - sender.sendMessage("Checking world, this could take a few moments..."); + sender.sendMessage("Starting game, please wait."); // 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 (!Game.getGame().startGame()) { // If game type does not exist, give sender feedback -- cgit v1.2.3 From d2c33ffb6258e3197f455035087c3bb5a1b0d662 Mon Sep 17 00:00:00 2001 From: Myles Date: Sat, 3 Dec 2022 14:13:00 -0600 Subject: AAH SPIDERS EVERYWHERE (bug fixes) --- src/main/java/com/MylesAndMore/tumble/Game.java | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index aa86e12..fd7e1a1 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -14,7 +14,10 @@ public class Game { private static Game gameInstance; // Private Game() constructor for singleton instance - private Game() { } + private Game() { + gameWorld = Bukkit.getWorld(TumbleManager.getGameWorld()); + gameSpawn = gameWorld.getSpawnLocation(); + } // ONLY Public method to get the game instance public static Game getGame() { @@ -24,19 +27,17 @@ public class Game { return gameInstance; } - - // Define local game vars // The gameType keeps the current game type (shocker) - private String gameType = null; + private String gameType; // The gameState keeps the current state of the game (I'm so creative, I know) - private String gameState = null; + private String gameState; // Initialize a new instance of the Random class for use later - private Random Random = new Random(); + private final Random Random = new Random(); // Define the game world and its spawnpoint as a new Location for use later - private World gameWorld = Bukkit.getWorld(TumbleManager.getGameWorld()); - private Location gameSpawn = gameWorld.getSpawnLocation(); + private final World gameWorld; + private final Location gameSpawn; // Make a list of the game's players for later private List gamePlayers = null; @@ -98,7 +99,8 @@ public class Game { } private boolean generateLayers(String gameType) { - Location layer = gameSpawn; + // Location layer = gameSpawn; + Location layer = new Location(gameSpawn.getWorld(), gameSpawn.getX(), gameSpawn.getY(), gameSpawn.getZ(), gameSpawn.getYaw(), gameSpawn.getPitch()); if (Objects.equals(gameType, "shovels")) { layer.setY(layer.getY() - 1); Generator.generateLayer(layer, 17, 1, Material.SNOW_BLOCK); @@ -107,7 +109,7 @@ public class Game { 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); + layer.setY(layer.getY() + 2); Generator.generateLayer(layer, 4, 2, Material.GRASS); } else if (Objects.equals(gameType, "snowballs")) { @@ -123,6 +125,7 @@ public class Game { else { return false; } + layer = null; return true; } @@ -178,6 +181,7 @@ public class Game { } private void gameEnd(@NotNull Player winner) { + gameState = "complete"; Bukkit.getServer().broadcastMessage(ChatColor.GREEN + winner.getName() + " has won!"); } -- cgit v1.2.3 From 6be45c6cdfb243fc872b7073729a755f8f1ee193 Mon Sep 17 00:00:00 2001 From: Myles Date: Sat, 3 Dec 2022 16:34:13 -0600 Subject: carver is too good at bug fixing --- src/main/java/com/MylesAndMore/tumble/Game.java | 6 ++---- src/main/java/com/MylesAndMore/tumble/Main.java | 6 ++---- .../com/MylesAndMore/tumble/commands/StartGame.java | 19 ------------------- src/main/resources/config.yml | 4 ++-- 4 files changed, 6 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index fd7e1a1..ccbbc55 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -153,9 +153,6 @@ public class Game { // 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 (Player aPlayer : TumbleManager.getPlayersInLobby()) { - //for (List playersInLobby = TumbleManager.getPlayersInLobby(); playersInLobby.size() > 0; playersInLobby = TumbleManager.getPlayersInLobby()) { - // Get a singular player from the player list - //Player aPlayer = playersInLobby.get(0); // Get a singular location from the scatter list Location aLocation = scatterLocations.get(0); // Teleport that player to that scatter location @@ -175,6 +172,7 @@ public class Game { // otherwise, the game must have two people left (and one just died), meaning it is over // This logic is so that it will not remove the last player standing from the list, so we know who the winner is. else { + gamePlayers.remove(player); // End the game, passing the winner to the gameEnd method gameEnd(gamePlayers.get(0)); } @@ -198,6 +196,6 @@ public class Game { // Methods to get the game type and game state for other classes outside the Game private String getGameType() { return gameType; } - private String getGameState() { return gameState; } + public String getGameState() { return gameState; } } \ No newline at end of file diff --git a/src/main/java/com/MylesAndMore/tumble/Main.java b/src/main/java/com/MylesAndMore/tumble/Main.java index 2a276d4..4ef6585 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; @@ -34,6 +32,6 @@ public class Main extends JavaPlugin{ } // Init message - Bukkit.getServer().getLogger().info("[tumble] tumble initialization complete!"); + Bukkit.getServer().getLogger().info("[tumble] Tumble initialization complete!"); } } \ No newline at end of file diff --git a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java index aad4b9e..85fd705 100644 --- a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java +++ b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java @@ -12,7 +12,6 @@ import org.bukkit.entity.Player; import java.util.List; public class StartGame implements CommandExecutor { - // Define the startGame method so that other classes can refrence it public void startGame(CommandSender sender, String[] args) { // Check if sender has perms to run command if (sender.hasPermission("tumble.start")) { @@ -60,24 +59,6 @@ public class StartGame implements CommandExecutor { } } - 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 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); diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index b2ba268..a881556 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -7,8 +7,8 @@ permissionMessage: You do not have permission to perform this command! # Customize the game mode of Tumble # Acceptable options include: shovels, snowballs, mixed -# Default is shovels -gameMode: shovels +# Default is mixed +gameMode: mixed # This tells the plugin which worlds it should use as the lobby/game worlds # Do NOT change unless you know what you're doing!! -- cgit v1.2.3 From bb1ece58ecda6f37c3002e6fd4eaa81d3ae0f2fc Mon Sep 17 00:00:00 2001 From: Myles Date: Sat, 3 Dec 2022 21:00:57 -0600 Subject: add [tumble] prefix --- src/main/java/com/MylesAndMore/tumble/Main.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Main.java b/src/main/java/com/MylesAndMore/tumble/Main.java index 4ef6585..862de47 100644 --- a/src/main/java/com/MylesAndMore/tumble/Main.java +++ b/src/main/java/com/MylesAndMore/tumble/Main.java @@ -23,12 +23,12 @@ 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 -- cgit v1.2.3 From a4125d14adefa32953f922c480ff47c7183b8440 Mon Sep 17 00:00:00 2001 From: CraivMan Date: Sat, 3 Dec 2022 23:06:22 -0600 Subject: Added cuboid generator (clear layers) --- .../java/com/MylesAndMore/tumble/api/Generator.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/java/com/MylesAndMore/tumble/api/Generator.java b/src/main/java/com/MylesAndMore/tumble/api/Generator.java index 632627d..5a1feba 100644 --- a/src/main/java/com/MylesAndMore/tumble/api/Generator.java +++ b/src/main/java/com/MylesAndMore/tumble/api/Generator.java @@ -24,4 +24,22 @@ public class Generator { } } } + + public static void generateCuboid(Location firstPos, Location secondPos, Material material) { + World world = firstPos.getWorld(); + 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); + } + } + } + } } -- cgit v1.2.3 From 3f407f0be20c1239c6f8e6ff75a06fbd2416bd02 Mon Sep 17 00:00:00 2001 From: CraivMan Date: Sat, 3 Dec 2022 23:11:17 -0600 Subject: Added round logic (PT 1) I did this all (100% without Myles) --- src/main/java/com/MylesAndMore/tumble/Game.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index ccbbc55..67eedca 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -165,9 +165,9 @@ public class Game { public void playerDeath(@NotNull Player player) { player.setGameMode(GameMode.SPECTATOR); // If there are more than 2 players in the game, - if (gamePlayers.size() > 2) { - // remove that player (who just died) from the gamePlayersArray, effectively eliminating them, - gamePlayers.remove(player); + if (roundPlayers.size() > 2) { + // remove that player (who just died) from the roundPlayersArray, effectively eliminating them, + roundPlayers.remove(player); } // otherwise, the game must have two people left (and one just died), meaning it is over // This logic is so that it will not remove the last player standing from the list, so we know who the winner is. -- cgit v1.2.3 From 001b3dc43d716443a83fab6996fe01a773b333e0 Mon Sep 17 00:00:00 2001 From: CraivMan Date: Sat, 3 Dec 2022 23:11:35 -0600 Subject: Added round logic (PT 2) I did this all (100% without myles) --- src/main/java/com/MylesAndMore/tumble/Game.java | 56 +++++++++++++++++++++---- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 67eedca..1326bd5 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -40,7 +40,11 @@ public class Game { private final Location gameSpawn; // Make a list of the game's players for later - private List gamePlayers = null; + private List gamePlayers; + // Make a list of the round's players + private List roundPlayers; + // Initialize a list to keep track of wins between rounds + private List gameWins; // Creates a new Game // This will return true if the game succeeds creation, and false if not @@ -94,6 +98,9 @@ public class Game { } // Update the game's players for later gamePlayers = new ArrayList<>(TumbleManager.getPlayersInGame()); + roundPlayers = new ArrayList<>(TumbleManager.getPlayersInGame()); + gameWins = new ArrayList<>(); + gameWins.addAll(List.of(0,0,0,0,0,0,0,0)); gameState = "running"; return true; } @@ -110,7 +117,7 @@ public class Game { layer.setY(layer.getY() - 1); Generator.generateLayer(layer, 4, 1, Material.PODZOL); layer.setY(layer.getY() + 2); - Generator.generateLayer(layer, 4, 2, Material.GRASS); + Generator.generateLayer(layer, 4, 2, Material.TALL_GRASS); } else if (Objects.equals(gameType, "snowballs")) { layer.setY(layer.getY() - 1); @@ -122,10 +129,17 @@ public class Game { layer.setY(layer.getY() - 1); Generator.generateLayer(layer, 4, 1, Material.LIME_GLAZED_TERRACOTTA); } + else if (Objects.equals(gameType, "mixed")) { + if (Random.nextInt(2) == 0) { + generateLayers("shovels"); + } else { + generateLayers("snowballs"); + } + } else { return false; } - layer = null; + // layer = null; return true; } @@ -172,15 +186,43 @@ public class Game { // otherwise, the game must have two people left (and one just died), meaning it is over // This logic is so that it will not remove the last player standing from the list, so we know who the winner is. else { - gamePlayers.remove(player); + // roundPlayers.remove(player); // End the game, passing the winner to the gameEnd method - gameEnd(gamePlayers.get(0)); + roundEnd(roundPlayers.get(0)); + } + } + + private void roundEnd(@NotNull Player winner) { + // Set the wins of the player to their current # of wins + 1 + gameWins.set(gamePlayers.indexOf(winner), (gameWins.get(gamePlayers.indexOf(winner)) + 1)); + Bukkit.getServer().broadcastMessage(ChatColor.GREEN + winner.getName() + " has won the round!"); + if (gameWins.get(gamePlayers.indexOf(winner)) == 3) { + gameEnd(winner); + } + else { + // Clear old layers + Location firstPos = new Location(gameSpawn.getWorld(), gameSpawn.getX() - 20, gameSpawn.getY() - 4, gameSpawn.getZ() - 20); + Location secondPos = new Location(gameSpawn.getWorld(), gameSpawn.getX() + 20, gameSpawn.getY(), gameSpawn.getZ() + 20); + Generator.generateCuboid(firstPos, secondPos, Material.AIR); + // Generate layers + // Debug + Bukkit.getServer().broadcastMessage(gameType); + generateLayers(gameType); + // Teleport players + // A new method will need to be written for this; current one only supports lobby + + // Set their gamemodes to survival + } } private void gameEnd(@NotNull Player winner) { - gameState = "complete"; - Bukkit.getServer().broadcastMessage(ChatColor.GREEN + winner.getName() + " has won!"); + Bukkit.getServer().broadcastMessage(ChatColor.GOLD + winner.getName() + " has won the game!"); + // Clear layers + Location firstPos = new Location(gameSpawn.getWorld(), gameSpawn.getX() - 20, gameSpawn.getY() - 4, gameSpawn.getZ() - 20); + Location secondPos = new Location(gameSpawn.getWorld(), gameSpawn.getX() + 20, gameSpawn.getY(), gameSpawn.getZ() + 20); + Generator.generateCuboid(firstPos, secondPos, Material.AIR); + // Send players back to lobby } private void giveItems(ItemStack itemStack) { -- cgit v1.2.3 From 6cd94e0cb19480bb638f8bebf602b100d81f0267 Mon Sep 17 00:00:00 2001 From: CraivMan Date: Sun, 4 Dec 2022 14:51:26 -0600 Subject: Prevented shovels from losing durability --- .../java/com/MylesAndMore/tumble/EventListener.java | 19 +++++++++++++++++++ src/main/java/com/MylesAndMore/tumble/Game.java | 18 +++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index 05f82fe..3f28e89 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -3,10 +3,14 @@ package com.MylesAndMore.tumble; import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerItemDamageEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; +import java.util.Objects; + public class EventListener implements Listener{ @EventHandler public void PlayerJoinEvent(PlayerJoinEvent event) { @@ -47,4 +51,19 @@ public class EventListener implements Listener{ } } } + + @EventHandler + public void ItemDamageEvent(PlayerItemDamageEvent event) { + // On a BlockBreakEvent, check to make sure there is a defined gameWorld + if (TumbleManager.getGameWorld() != null) { + // Then check to see if the block was broken in the gameWorld, + if (event.getPlayer().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) { + // If it was in the gameWorld, pass this event to the Game + Game.getGame().itemDamage(event); + } + } + } } + + + diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 1326bd5..7a6512d 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -3,7 +3,11 @@ package com.MylesAndMore.tumble; import com.MylesAndMore.tumble.api.Generator; import org.bukkit.*; import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerItemDamageEvent; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -29,7 +33,7 @@ public class Game { // Define local game vars // The gameType keeps the current game type (shocker) - private String gameType; + private static String gameType; // The gameState keeps the current state of the game (I'm so creative, I know) private String gameState; @@ -61,6 +65,8 @@ public class Game { giveItems(new ItemStack(Material.DIAMOND_SHOVEL)); // Send players to the game sendPlayers(); + + // Keep in mind that after this runs, this command will complete and return true } else { @@ -118,6 +124,7 @@ public class Game { Generator.generateLayer(layer, 4, 1, Material.PODZOL); layer.setY(layer.getY() + 2); Generator.generateLayer(layer, 4, 2, Material.TALL_GRASS); + roundType = "shovels"; } else if (Objects.equals(gameType, "snowballs")) { layer.setY(layer.getY() - 1); @@ -128,6 +135,7 @@ public class Game { Generator.generateLayer(layer, 4, 1, Material.AIR); layer.setY(layer.getY() - 1); Generator.generateLayer(layer, 4, 1, Material.LIME_GLAZED_TERRACOTTA); + roundType = "snowballs"; } else if (Objects.equals(gameType, "mixed")) { if (Random.nextInt(2) == 0) { @@ -176,6 +184,14 @@ public class Game { } } + public void itemDamage(PlayerItemDamageEvent event) { + // If the game type is shovels, + if (Objects.equals(roundType, "shovels")) { + // Cancel the event + event.setCancelled(true); + } + } + public void playerDeath(@NotNull Player player) { player.setGameMode(GameMode.SPECTATOR); // If there are more than 2 players in the game, -- cgit v1.2.3 From 08d5fccac27fb1cb9cca3b3c69b07d916c37c195 Mon Sep 17 00:00:00 2001 From: CraivMan Date: Sun, 4 Dec 2022 14:52:36 -0600 Subject: Prevented shovels from losing durability (PT 2) --- src/main/java/com/MylesAndMore/tumble/Game.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 7a6512d..887c4ee 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -36,6 +36,8 @@ public class Game { private static String gameType; // The gameState keeps the current state of the game (I'm so creative, I know) private String gameState; + // Define a variable for the roundType + private String roundType; // Initialize a new instance of the Random class for use later private final Random Random = new Random(); @@ -140,8 +142,10 @@ public class Game { else if (Objects.equals(gameType, "mixed")) { if (Random.nextInt(2) == 0) { generateLayers("shovels"); + roundType = "shovels"; } else { generateLayers("snowballs"); + roundType = "snowballs"; } } else { -- cgit v1.2.3 From 1919d888bf9594f2341cb0be8ae8d3a7fdd1fb95 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Mon, 5 Dec 2022 10:25:15 -0600 Subject: things have (maybe) been done --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bfe1a54..ea3c1d9 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele ## game realism -- [ ] make the shovel in shovels mode not lose any durabilty +- [x] make the shovel in shovels mode not lose any durabilty - [ ] make the game blocks breakable very fast, but **not instantly--very important for balancing!!** - [ ] add infinite snowballs in the gamemanager for tumble mode - [ ] make it so that you can't remove any of the game items from your inventory @@ -21,7 +21,7 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele ## game logic (fyi: very object-oriented) -- [ ] make a Game class and object that we can initialize a new instance of with a gameType +- [x] make a Game class and object that we can initialize a new instance of with a gameType - [ ] within this game object, while games are running: - [ ] prevent players from joining/autojoining during - [ ] keep track of when someone wins; start a new round when this happens -- cgit v1.2.3 From 14b9a1aec413fc0affe7de02e5d875e251bb15dd Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Mon, 5 Dec 2022 19:20:54 +0000 Subject: reformatting (this may break things) removed some flagged imports and changed some of the regen code might need to revert the commit... --- .../com/MylesAndMore/tumble/EventListener.java | 3 --- src/main/java/com/MylesAndMore/tumble/Game.java | 23 ++++++---------------- .../com/MylesAndMore/tumble/api/Generator.java | 1 - .../MylesAndMore/tumble/commands/StartGame.java | 4 ---- 4 files changed, 6 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index 3f28e89..1a8be98 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -3,14 +3,11 @@ package com.MylesAndMore.tumble; import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerItemDamageEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; -import java.util.Objects; - public class EventListener implements Listener{ @EventHandler public void PlayerJoinEvent(PlayerJoinEvent event) { diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 887c4ee..8a81e01 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -3,11 +3,8 @@ package com.MylesAndMore.tumble; import com.MylesAndMore.tumble.api.Generator; import org.bukkit.*; import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerItemDamageEvent; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -67,8 +64,6 @@ public class Game { giveItems(new ItemStack(Material.DIAMOND_SHOVEL)); // Send players to the game sendPlayers(); - - // Keep in mind that after this runs, this command will complete and return true } else { @@ -78,7 +73,6 @@ public class Game { else if (Objects.equals(TumbleManager.getGameType(), "snowballs")) { gameType = "snowballs"; if (generateLayers(gameType)) { - // Reminder: we need a way to make this snowball infinite! giveItems(new ItemStack(Material.SNOWBALL)); sendPlayers(); } @@ -216,17 +210,15 @@ public class Game { // Set the wins of the player to their current # of wins + 1 gameWins.set(gamePlayers.indexOf(winner), (gameWins.get(gamePlayers.indexOf(winner)) + 1)); Bukkit.getServer().broadcastMessage(ChatColor.GREEN + winner.getName() + " has won the round!"); + // Clear old layers (as a fill command, this would be /fill ~-20 ~-4 ~-20 ~20 ~ ~20 relative to spawn) + Generator.generateCuboid(new Location(gameSpawn.getWorld(), gameSpawn.getX() - 20, gameSpawn.getY() - 4, gameSpawn.getZ() - 20), new Location(gameSpawn.getWorld(), gameSpawn.getX() + 20, gameSpawn.getY(), gameSpawn.getZ() + 20), Material.AIR); + // 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 { - // Clear old layers - Location firstPos = new Location(gameSpawn.getWorld(), gameSpawn.getX() - 20, gameSpawn.getY() - 4, gameSpawn.getZ() - 20); - Location secondPos = new Location(gameSpawn.getWorld(), gameSpawn.getX() + 20, gameSpawn.getY(), gameSpawn.getZ() + 20); - Generator.generateCuboid(firstPos, secondPos, Material.AIR); - // Generate layers - // Debug - Bukkit.getServer().broadcastMessage(gameType); + // Re-generate layers generateLayers(gameType); // Teleport players // A new method will need to be written for this; current one only supports lobby @@ -238,10 +230,7 @@ public class Game { private void gameEnd(@NotNull Player winner) { Bukkit.getServer().broadcastMessage(ChatColor.GOLD + winner.getName() + " has won the game!"); - // Clear layers - Location firstPos = new Location(gameSpawn.getWorld(), gameSpawn.getX() - 20, gameSpawn.getY() - 4, gameSpawn.getZ() - 20); - Location secondPos = new Location(gameSpawn.getWorld(), gameSpawn.getX() + 20, gameSpawn.getY(), gameSpawn.getZ() + 20); - Generator.generateCuboid(firstPos, secondPos, Material.AIR); + // Send players back to lobby } diff --git a/src/main/java/com/MylesAndMore/tumble/api/Generator.java b/src/main/java/com/MylesAndMore/tumble/api/Generator.java index 5a1feba..1be071d 100644 --- a/src/main/java/com/MylesAndMore/tumble/api/Generator.java +++ b/src/main/java/com/MylesAndMore/tumble/api/Generator.java @@ -17,7 +17,6 @@ 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); } } diff --git a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java index 85fd705..2e531ef 100644 --- a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java +++ b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java @@ -2,14 +2,10 @@ package com.MylesAndMore.tumble.commands; 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; public class StartGame implements CommandExecutor { public void startGame(CommandSender sender, String[] args) { -- cgit v1.2.3 From f4c447ec2a39a1782b6e7aa83e8ad1ef65c85d35 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Mon, 5 Dec 2022 19:29:56 +0000 Subject: reformatting pt.2 this one *shouldn't* break everything (but that's what they all say) --- src/main/java/com/MylesAndMore/tumble/Game.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 8a81e01..8f0af60 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -49,8 +49,10 @@ public class Game { // Initialize a list to keep track of wins between rounds private List gameWins; - // Creates a new Game - // This will return true if the game succeeds creation, and false if not + /** + * Creates a new Game + * @return true if the game succeeds creation, and false if not + */ public boolean startGame() { gameState = "starting"; if (Objects.equals(TumbleManager.getGameType(), "shovels")) { @@ -108,7 +110,6 @@ public class Game { } private boolean generateLayers(String gameType) { - // Location layer = gameSpawn; Location layer = new Location(gameSpawn.getWorld(), gameSpawn.getX(), gameSpawn.getY(), gameSpawn.getZ(), gameSpawn.getYaw(), gameSpawn.getPitch()); if (Objects.equals(gameType, "shovels")) { layer.setY(layer.getY() - 1); @@ -145,7 +146,6 @@ public class Game { else { return false; } - // layer = null; return true; } -- cgit v1.2.3 From c4375578c74f13993209d7b3673e91ab3f9b81d2 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Mon, 5 Dec 2022 21:13:53 +0000 Subject: add gamemode switching at end of round --- src/main/java/com/MylesAndMore/tumble/Game.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 8f0af60..63c68df 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -182,6 +182,15 @@ public class Game { } } + private void setSurvival() { + for (List spectators = gamePlayers; spectators.size() > 0; spectators.remove(0)) { + // Get a singular player from the player list + Player spectatorPlayer = spectators.get(0); + // Set that player's gamemode to survival + spectatorPlayer.setGameMode(GameMode.SURVIVAL); + } + } + public void itemDamage(PlayerItemDamageEvent event) { // If the game type is shovels, if (Objects.equals(roundType, "shovels")) { @@ -224,7 +233,7 @@ public class Game { // A new method will need to be written for this; current one only supports lobby // Set their gamemodes to survival - + setSurvival(); } } -- cgit v1.2.3 From cc6e428517da5fe6acd3659bfbe4ebd4fa3ea5a5 Mon Sep 17 00:00:00 2001 From: CraivMan Date: Mon, 5 Dec 2022 21:09:50 -0600 Subject: Infinite snowballs (unfixed) --- .../com/MylesAndMore/tumble/EventListener.java | 25 ++++++++++++++++++++++ src/main/java/com/MylesAndMore/tumble/Game.java | 9 ++++---- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index 3f28e89..f870ed0 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -1,13 +1,22 @@ package com.MylesAndMore.tumble; import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.entity.Snowball; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.entity.ProjectileLaunchEvent; +import org.bukkit.event.player.PlayerItemConsumeEvent; import org.bukkit.event.player.PlayerItemDamageEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import org.bukkit.projectiles.ProjectileSource; import java.util.Objects; @@ -63,7 +72,23 @@ public class EventListener implements Listener{ } } } + + @EventHandler + public void ProjectileLaunchEvent(ProjectileLaunchEvent event) { + // When A projectile is launched, check to make sure there is a defined gameWorld + if (TumbleManager.getGameWorld() != null) { + // Then 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) { + player.getInventory().addItem(new ItemStack(Material.SNOWBALL)); + } + } + } + } + } } + diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 887c4ee..53a167c 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -90,14 +90,17 @@ public class Game { gameType = "mixed"; // Mixed gamemode (choose random shovels or snowballs) if (Random.nextInt(2) == 0) { + roundType = "shovels"; generateLayers("shovels"); giveItems(new ItemStack(Material.DIAMOND_SHOVEL)); sendPlayers(); } else { + roundType = "snowballs"; generateLayers("snowballs"); giveItems(new ItemStack(Material.SNOWBALL)); sendPlayers(); + } } else { @@ -116,7 +119,7 @@ public class Game { private boolean generateLayers(String gameType) { // Location layer = gameSpawn; Location layer = new Location(gameSpawn.getWorld(), gameSpawn.getX(), gameSpawn.getY(), gameSpawn.getZ(), gameSpawn.getYaw(), gameSpawn.getPitch()); - if (Objects.equals(gameType, "shovels")) { + if (Objects.equals(roundType, "shovels")) { layer.setY(layer.getY() - 1); Generator.generateLayer(layer, 17, 1, Material.SNOW_BLOCK); Generator.generateLayer(layer, 13, 1, Material.AIR); @@ -128,7 +131,7 @@ public class Game { Generator.generateLayer(layer, 4, 2, Material.TALL_GRASS); roundType = "shovels"; } - else if (Objects.equals(gameType, "snowballs")) { + else if (Objects.equals(roundType, "snowballs")) { layer.setY(layer.getY() - 1); Generator.generateLayer(layer, 17, 1, Material.COAL_ORE); Generator.generateLayer(layer, 13, 1, Material.AIR); @@ -142,10 +145,8 @@ public class Game { else if (Objects.equals(gameType, "mixed")) { if (Random.nextInt(2) == 0) { generateLayers("shovels"); - roundType = "shovels"; } else { generateLayers("snowballs"); - roundType = "snowballs"; } } else { -- cgit v1.2.3 From fd2c4ff5d73894760e2dc1c7ced531f69b785c6c Mon Sep 17 00:00:00 2001 From: CraivMan Date: Mon, 5 Dec 2022 21:10:53 -0600 Subject: Infinite snowballs (unfixed) #2 --- src/main/java/com/MylesAndMore/tumble/Game.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index b08dfd3..16916ff 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -253,7 +253,6 @@ public class Game { } } - // Methods to get the game type and game state for other classes outside the Game private String getGameType() { return gameType; } -- cgit v1.2.3 From 81a433dbbae4ac4494e6084c166608fa40fe23b7 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Tue, 6 Dec 2022 16:57:53 +0000 Subject: me when the imports are unused --- src/main/java/com/MylesAndMore/tumble/EventListener.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index f40430d..b91ed56 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -3,19 +3,15 @@ package com.MylesAndMore.tumble; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; -import org.bukkit.entity.Projectile; import org.bukkit.entity.Snowball; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.entity.ProjectileLaunchEvent; -import org.bukkit.event.player.PlayerItemConsumeEvent; import org.bukkit.event.player.PlayerItemDamageEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; -import org.bukkit.projectiles.ProjectileSource; public class EventListener implements Listener{ @EventHandler -- cgit v1.2.3 From 43761076f359278756dfcddbcdeeca14b45c6f2b Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Tue, 6 Dec 2022 17:15:24 +0000 Subject: new tp method and more comments --- src/main/java/com/MylesAndMore/tumble/Game.java | 72 +++++++++++++++++++------ 1 file changed, 56 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 16916ff..793d4dd 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -30,7 +30,7 @@ public class Game { // Define local game vars // The gameType keeps the current game type (shocker) - private static String gameType; + private static String gameType = TumbleManager.getGameType(); // The gameState keeps the current state of the game (I'm so creative, I know) private String gameState; // Define a variable for the roundType @@ -56,16 +56,15 @@ public class Game { public boolean startGame() { gameState = "starting"; if (Objects.equals(TumbleManager.getGameType(), "shovels")) { - // Set the correct gameType for the game we're playing, for later - gameType = "shovels"; + // Set the roundType to gameType since it won't change for this mode + roundType = gameType; // Generate the correct layers for a Shovels game // The else statement is just in case the generator fails; this command will fail if (generateLayers(gameType)) { // If the layer generation succeeds, give players diamond shovels - // Reminder: we need a way for blocks to break instantly and for these to not lose durability! giveItems(new ItemStack(Material.DIAMOND_SHOVEL)); - // Send players to the game - sendPlayers(); + // Send all players from lobby to the game + teleportPlayers(TumbleManager.getPlayersInLobby()); // Keep in mind that after this runs, this command will complete and return true } else { @@ -73,45 +72,51 @@ public class Game { } } else if (Objects.equals(TumbleManager.getGameType(), "snowballs")) { - gameType = "snowballs"; + roundType = gameType; if (generateLayers(gameType)) { giveItems(new ItemStack(Material.SNOWBALL)); - sendPlayers(); + teleportPlayers(TumbleManager.getPlayersInLobby()); } else { return false; } } else if (Objects.equals(TumbleManager.getGameType(), "mixed")) { - gameType = "mixed"; - // Mixed gamemode (choose random shovels or snowballs) + // Mixed gamemode (choose random shovels/0 or snowballs/1) if (Random.nextInt(2) == 0) { roundType = "shovels"; generateLayers("shovels"); giveItems(new ItemStack(Material.DIAMOND_SHOVEL)); - sendPlayers(); + teleportPlayers(TumbleManager.getPlayersInLobby()); } else { roundType = "snowballs"; generateLayers("snowballs"); giveItems(new ItemStack(Material.SNOWBALL)); - sendPlayers(); - + teleportPlayers(TumbleManager.getPlayersInLobby()); } } else { // 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)); gameState = "running"; return true; } + /** + * Generates the layers in the gameWorld for a certain gameType + * @param gameType 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 gameType) { Location layer = new Location(gameSpawn.getWorld(), gameSpawn.getX(), gameSpawn.getY(), gameSpawn.getZ(), gameSpawn.getYaw(), gameSpawn.getPitch()); if (Objects.equals(roundType, "shovels")) { @@ -150,6 +155,9 @@ public class Game { return true; } + // THIS METHOD IS DEPRECATED!! + // It has been replaced by teleportPlayers(), I'm just leaving this just in case teleportPlayers() doesn't work out + /** private void sendPlayers() { // Get the X, Y, and Z coords of that location double x = gameSpawn.getX(); @@ -182,6 +190,39 @@ public class Game { scatterLocations.remove(0); } } + */ + + /** + * Teleports a list of players to the specified scatter locations in the gameWorld + * @param players a List of Players to teleport + */ + private void teleportPlayers(List 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 scatterLocations = new ArrayList<>(); + scatterLocations.addAll(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 setSurvival() { for (List spectators = gamePlayers; spectators.size() > 0; spectators.remove(0)) { @@ -230,9 +271,8 @@ public class Game { else { // Re-generate layers generateLayers(gameType); - // Teleport players - // A new method will need to be written for this; current one only supports lobby - + // Re-scatter players + teleportPlayers(gamePlayers); // Set their gamemodes to survival setSurvival(); } -- cgit v1.2.3 From 1b8759700824b2195385c68f9ed41104774180e7 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Tue, 6 Dec 2022 17:20:28 +0000 Subject: we do a little reformatting of the ItemDamage event to keep it all in one location sorry Carver, it's just easier to read :) --- src/main/java/com/MylesAndMore/tumble/EventListener.java | 8 ++++++-- src/main/java/com/MylesAndMore/tumble/Game.java | 10 +--------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index b91ed56..86bf851 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -1,5 +1,7 @@ package com.MylesAndMore.tumble; +import java.util.Objects; + import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -60,8 +62,10 @@ public class EventListener implements Listener{ if (TumbleManager.getGameWorld() != null) { // Then check to see if the block was broken in the gameWorld, if (event.getPlayer().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) { - // If it was in the gameWorld, pass this event to the Game - Game.getGame().itemDamage(event); + // If it was in the gameWorld, check if the roundType was shovels + if (Objects.equals(Game.getGame().getRoundType(), "shovels")) { + event.setCancelled(true); + } } } } diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 793d4dd..6655081 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -233,14 +233,6 @@ public class Game { } } - public void itemDamage(PlayerItemDamageEvent event) { - // If the game type is shovels, - if (Objects.equals(roundType, "shovels")) { - // Cancel the event - event.setCancelled(true); - } - } - public void playerDeath(@NotNull Player player) { player.setGameMode(GameMode.SPECTATOR); // If there are more than 2 players in the game, @@ -294,7 +286,7 @@ public class Game { } // Methods to get the game type and game state for other classes outside the Game - private String getGameType() { return gameType; } + public String getRoundType() { return roundType; } public String getGameState() { return gameState; } -- cgit v1.2.3 From 8681c9fa319b2e13a23465aef9b13cd1255faab3 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Tue, 6 Dec 2022 17:33:31 +0000 Subject: more modularity and reformatting and performance!! --- src/main/java/com/MylesAndMore/tumble/Game.java | 98 +++++++++++++++---------- 1 file changed, 59 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 6655081..4142aba 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -3,7 +3,6 @@ package com.MylesAndMore.tumble; import com.MylesAndMore.tumble.api.Generator; import org.bukkit.*; import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerItemDamageEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; @@ -28,6 +27,7 @@ public class Game { return gameInstance; } + // Define local game vars // The gameType keeps the current game type (shocker) private static String gameType = TumbleManager.getGameType(); @@ -42,6 +42,8 @@ public class Game { private final World gameWorld; private final Location gameSpawn; + // Make a list of the lobby's players for later + private List lobbyPlayers = TumbleManager.getPlayersInLobby(); // Make a list of the game's players for later private List gamePlayers; // Make a list of the round's players @@ -49,6 +51,9 @@ public class Game { // Initialize a list to keep track of wins between rounds private List gameWins; + + // BEGIN PUBLIC METHODS + /** * Creates a new Game * @return true if the game succeeds creation, and false if not @@ -62,9 +67,9 @@ public class Game { // The else statement is just in case the generator fails; this command will fail if (generateLayers(gameType)) { // If the layer generation succeeds, give players diamond shovels - giveItems(new ItemStack(Material.DIAMOND_SHOVEL)); + giveItems(lobbyPlayers, new ItemStack(Material.DIAMOND_SHOVEL)); // Send all players from lobby to the game - teleportPlayers(TumbleManager.getPlayersInLobby()); + teleportPlayers(lobbyPlayers); // Keep in mind that after this runs, this command will complete and return true } else { @@ -74,8 +79,8 @@ public class Game { else if (Objects.equals(TumbleManager.getGameType(), "snowballs")) { roundType = gameType; if (generateLayers(gameType)) { - giveItems(new ItemStack(Material.SNOWBALL)); - teleportPlayers(TumbleManager.getPlayersInLobby()); + giveItems(lobbyPlayers, new ItemStack(Material.SNOWBALL)); + teleportPlayers(lobbyPlayers); } else { return false; @@ -86,14 +91,14 @@ public class Game { if (Random.nextInt(2) == 0) { roundType = "shovels"; generateLayers("shovels"); - giveItems(new ItemStack(Material.DIAMOND_SHOVEL)); - teleportPlayers(TumbleManager.getPlayersInLobby()); + giveItems(lobbyPlayers, new ItemStack(Material.DIAMOND_SHOVEL)); + teleportPlayers(lobbyPlayers); } else { roundType = "snowballs"; generateLayers("snowballs"); - giveItems(new ItemStack(Material.SNOWBALL)); - teleportPlayers(TumbleManager.getPlayersInLobby()); + giveItems(lobbyPlayers, new ItemStack(Material.SNOWBALL)); + teleportPlayers(lobbyPlayers); } } else { @@ -112,12 +117,48 @@ public class Game { return true; } + /** + * This method should be called on the death of one of the Game's players + * @param player The player who died + */ + public void playerDeath(@NotNull Player player) { + player.setGameMode(GameMode.SPECTATOR); + // If there are more than 2 players in the game, + if (roundPlayers.size() > 2) { + // remove that player (who just died) from the roundPlayersArray, effectively eliminating them, + roundPlayers.remove(player); + } + // Otherwise, the game must have two people left (and one just died), meaning it is over + // This logic is so that it will not remove the last player standing from the list, so we know who the winner is. + else { + // roundPlayers.remove(player); + // 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 round type of the current round as a String ("shovels", "snowballs") + */ + public String getRoundType() { return roundType; } + + /** + * @return The game's current state as a String ("starting", "running", "complete") + */ + public String getGameState() { return gameState; } + + + // BEGIN PRIVATE METHODS + /** * Generates the layers in the gameWorld for a certain gameType * @param gameType 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 gameType) { + // 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(roundType, "shovels")) { layer.setY(layer.getY() - 1); @@ -143,18 +184,27 @@ public class Game { roundType = "snowballs"; } else if (Objects.equals(gameType, "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; } + private void giveItems(List 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); + } + } + // THIS METHOD IS DEPRECATED!! // It has been replaced by teleportPlayers(), I'm just leaving this just in case teleportPlayers() doesn't work out /** @@ -233,22 +283,6 @@ public class Game { } } - public void playerDeath(@NotNull Player player) { - player.setGameMode(GameMode.SPECTATOR); - // If there are more than 2 players in the game, - if (roundPlayers.size() > 2) { - // remove that player (who just died) from the roundPlayersArray, effectively eliminating them, - roundPlayers.remove(player); - } - // otherwise, the game must have two people left (and one just died), meaning it is over - // This logic is so that it will not remove the last player standing from the list, so we know who the winner is. - else { - // roundPlayers.remove(player); - // End the game, passing the winner to the gameEnd method - roundEnd(roundPlayers.get(0)); - } - } - private void roundEnd(@NotNull Player winner) { // Set the wins of the player to their current # of wins + 1 gameWins.set(gamePlayers.indexOf(winner), (gameWins.get(gamePlayers.indexOf(winner)) + 1)); @@ -272,22 +306,8 @@ public class Game { private void gameEnd(@NotNull Player winner) { Bukkit.getServer().broadcastMessage(ChatColor.GOLD + winner.getName() + " has won the game!"); - // Send players back to lobby - } - private void giveItems(ItemStack itemStack) { - for (List 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); - } } - // Methods to get the game type and game state for other classes outside the Game - public String getRoundType() { return roundType; } - - public String getGameState() { return gameState; } - } \ No newline at end of file -- cgit v1.2.3 From 7ae758f3cb0f129d46331e7682130b2f326c432f Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Tue, 6 Dec 2022 19:11:05 +0000 Subject: roundEnd maybe works now wheeee also more reformatting because I will never be satisfied with my code --- src/main/java/com/MylesAndMore/tumble/Game.java | 49 ++++++++++++++----------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 4142aba..470b99b 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -4,7 +4,6 @@ import com.MylesAndMore.tumble.api.Generator; import org.bukkit.*; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; import java.util.*; @@ -69,7 +68,7 @@ public class Game { // If the layer generation succeeds, give players diamond shovels giveItems(lobbyPlayers, new ItemStack(Material.DIAMOND_SHOVEL)); // Send all players from lobby to the game - teleportPlayers(lobbyPlayers); + scatterPlayers(lobbyPlayers); // Keep in mind that after this runs, this command will complete and return true } else { @@ -80,7 +79,7 @@ public class Game { roundType = gameType; if (generateLayers(gameType)) { giveItems(lobbyPlayers, new ItemStack(Material.SNOWBALL)); - teleportPlayers(lobbyPlayers); + scatterPlayers(lobbyPlayers); } else { return false; @@ -92,13 +91,13 @@ public class Game { roundType = "shovels"; generateLayers("shovels"); giveItems(lobbyPlayers, new ItemStack(Material.DIAMOND_SHOVEL)); - teleportPlayers(lobbyPlayers); + scatterPlayers(lobbyPlayers); } else { roundType = "snowballs"; generateLayers("snowballs"); giveItems(lobbyPlayers, new ItemStack(Material.SNOWBALL)); - teleportPlayers(lobbyPlayers); + scatterPlayers(lobbyPlayers); } } else { @@ -121,7 +120,7 @@ public class Game { * This method should be called on the death of one of the Game's players * @param player The player who died */ - public void playerDeath(@NotNull Player player) { + public void playerDeath(Player player) { player.setGameMode(GameMode.SPECTATOR); // If there are more than 2 players in the game, if (roundPlayers.size() > 2) { @@ -198,6 +197,11 @@ public class Game { 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 players, ItemStack itemStack) { for (Player aPlayer : players) { // Get a singular player from the player list and give that player the specified item @@ -205,6 +209,18 @@ public class Game { } } + /** + * 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 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); + } + } + // THIS METHOD IS DEPRECATED!! // It has been replaced by teleportPlayers(), I'm just leaving this just in case teleportPlayers() doesn't work out /** @@ -246,7 +262,7 @@ public class Game { * Teleports a list of players to the specified scatter locations in the gameWorld * @param players a List of Players to teleport */ - private void teleportPlayers(List players) { + private void scatterPlayers(List players) { // Get the coords of the game's spawn location double x = gameSpawn.getX(); double y = gameSpawn.getY(); @@ -274,16 +290,7 @@ public class Game { } } - private void setSurvival() { - for (List spectators = gamePlayers; spectators.size() > 0; spectators.remove(0)) { - // Get a singular player from the player list - Player spectatorPlayer = spectators.get(0); - // Set that player's gamemode to survival - spectatorPlayer.setGameMode(GameMode.SURVIVAL); - } - } - - private void roundEnd(@NotNull Player winner) { + private void roundEnd(Player winner) { // Set the wins of the player to their current # of wins + 1 gameWins.set(gamePlayers.indexOf(winner), (gameWins.get(gamePlayers.indexOf(winner)) + 1)); Bukkit.getServer().broadcastMessage(ChatColor.GREEN + winner.getName() + " has won the round!"); @@ -298,16 +305,16 @@ public class Game { // Re-generate layers generateLayers(gameType); // Re-scatter players - teleportPlayers(gamePlayers); + scatterPlayers(gamePlayers); // Set their gamemodes to survival - setSurvival(); + setGamemode(gamePlayers, GameMode.SURVIVAL); } } - private void gameEnd(@NotNull Player winner) { + private void gameEnd(Player winner) { Bukkit.getServer().broadcastMessage(ChatColor.GOLD + winner.getName() + " has won the game!"); // Send players back to lobby - + } } \ No newline at end of file -- cgit v1.2.3 From 94f6bbf48b8e0daa0c01a8723dc57bec326fbdcf Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Tue, 6 Dec 2022 21:44:55 +0000 Subject: finish the gameEnd method --- src/main/java/com/MylesAndMore/tumble/Game.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 470b99b..d2097d6 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -312,9 +312,12 @@ public class Game { } private void gameEnd(Player winner) { + // Announce win Bukkit.getServer().broadcastMessage(ChatColor.GOLD + winner.getName() + " has won the game!"); - // Send players back to lobby - + // Send all players back to lobby (spawn) + for (Player aPlayer : gamePlayers) { + aPlayer.teleport(Bukkit.getWorld(TumbleManager.getLobbyWorld()).getSpawnLocation()); + } } } \ No newline at end of file -- cgit v1.2.3 From 219e94232e53dedfe1ddc45f0a7cfa94e398bfeb Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Tue, 6 Dec 2022 15:50:17 -0600 Subject: Dedication is when you: Forget about ONE PART of the method so then you get on your phone in the GitHub web ui and change it (much harder than it seems!!) Added change game modes to game end --- src/main/java/com/MylesAndMore/tumble/Game.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index d2097d6..05ac05f 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -314,10 +314,12 @@ public class Game { private void gameEnd(Player winner) { // Announce win Bukkit.getServer().broadcastMessage(ChatColor.GOLD + winner.getName() + " has won the game!"); + // Set their gamemodes to survival + setGamemode(gamePlayers, GameMode.SURVIVAL); // Send all players back to lobby (spawn) for (Player aPlayer : gamePlayers) { aPlayer.teleport(Bukkit.getWorld(TumbleManager.getLobbyWorld()).getSpawnLocation()); } } -} \ No newline at end of file +} -- cgit v1.2.3 From c2357ce5246598c520c8c8e27aadb5bbce3dcc0e Mon Sep 17 00:00:00 2001 From: CraivMan Date: Tue, 6 Dec 2022 20:08:31 -0600 Subject: GIVING ITEMS IS SO ANNOYING! (And prevented item dropping) --- src/main/java/com/MylesAndMore/tumble/EventListener.java | 16 +++++++++++++++- src/main/java/com/MylesAndMore/tumble/Main.java | 10 +++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index 86bf851..4c3d154 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -10,6 +10,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.entity.ProjectileLaunchEvent; +import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerItemDamageEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; @@ -78,12 +79,25 @@ public class EventListener implements Listener{ if (event.getEntity().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) { if (event.getEntity() instanceof Snowball) { if (event.getEntity().getShooter() instanceof Player player) { - player.getInventory().addItem(new ItemStack(Material.SNOWBALL)); + player.getInventory().addItem(new ItemStack(Material.SNOWBALL,1)); } } } } } + + + @EventHandler + public void PlayerDropItemEvent(PlayerDropItemEvent event) { + // When an item is dropped, make sure there is a defined gameWorld + if (TumbleManager.getGameWorld() != null) { + // Then check if the item was dropped in the game world + if (event.getPlayer().getWorld() == Bukkit.getWorld((TumbleManager.getGameWorld()))) { + event.setCancelled(true); + + } + } + } } diff --git a/src/main/java/com/MylesAndMore/tumble/Main.java b/src/main/java/com/MylesAndMore/tumble/Main.java index 862de47..5c08907 100644 --- a/src/main/java/com/MylesAndMore/tumble/Main.java +++ b/src/main/java/com/MylesAndMore/tumble/Main.java @@ -23,15 +23,15 @@ public class Main extends JavaPlugin{ // Check if worlds are null in config if (TumbleManager.getGameWorld() == null) { - Bukkit.getServer().getLogger().warning("[tumble] It appears you have not configured a game world for Tumble."); - Bukkit.getServer().getLogger().info("[tumble] If this is your first time running the plugin, you may disregard this message."); + Bukkit.getServer().getLogger().warning("[Tumble] It appears you have not configured a game world for Tumble."); + Bukkit.getServer().getLogger().info("[Tumble] If this is your first time running the plugin, you may disregard this message."); } if (TumbleManager.getLobbyWorld() == null) { - Bukkit.getServer().getLogger().warning("[tumble] It appears you have not configured a lobby world for Tumble."); - Bukkit.getServer().getLogger().info("[tumble] If this is your first time running the plugin, you may disregard this message."); + 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 initialization complete!"); + Bukkit.getServer().getLogger().info("[Tumble] Tumble initialization complete!"); } } \ No newline at end of file -- cgit v1.2.3 From acaca4200a8c5479fb8f7be0c06a3b0064591c43 Mon Sep 17 00:00:00 2001 From: Myles Date: Tue, 6 Dec 2022 21:22:10 -0600 Subject: add delay in gameEnd --- src/main/java/com/MylesAndMore/tumble/Game.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 05ac05f..5b594fa 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -314,12 +314,19 @@ public class Game { private void gameEnd(Player winner) { // Announce win Bukkit.getServer().broadcastMessage(ChatColor.GOLD + winner.getName() + " has won the game!"); - // Set their gamemodes to survival - setGamemode(gamePlayers, GameMode.SURVIVAL); - // Send all players back to lobby (spawn) - for (Player aPlayer : gamePlayers) { - aPlayer.teleport(Bukkit.getWorld(TumbleManager.getLobbyWorld()).getSpawnLocation()); - } + Bukkit.getServer().broadcastMessage(ChatColor.GREEN + "Teleporting in five seconds..."); + // Wait 5s (100t), then + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), new Runnable() { + @Override + public void run() { + // Set their gamemodes to survival + setGamemode(gamePlayers, GameMode.SURVIVAL); + // Send all players back to lobby (spawn) + for (Player aPlayer : gamePlayers) { + aPlayer.teleport(Bukkit.getWorld(TumbleManager.getLobbyWorld()).getSpawnLocation()); + } + } + }, 100); } } -- cgit v1.2.3 From 8d81ae1ee0687b297dfa277bbd58467e6d4283d9 Mon Sep 17 00:00:00 2001 From: Myles Date: Tue, 6 Dec 2022 22:08:29 -0600 Subject: I love when there's more things to do! --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ea3c1d9..fd89174 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele ## game realism - [x] make the shovel in shovels mode not lose any durabilty +- [ ] make it so that you can't move until the game begins - [ ] make the game blocks breakable very fast, but **not instantly--very important for balancing!!** - [ ] add infinite snowballs in the gamemanager for tumble mode - [ ] make it so that you can't remove any of the game items from your inventory -- cgit v1.2.3 From eb95848cb47a86e8f21bdcce9afe552f8dc14707 Mon Sep 17 00:00:00 2001 From: Myles Date: Tue, 6 Dec 2022 22:09:40 -0600 Subject: look we have fancy titles now! and just a *quick* side note, everything actually works now basically: bug fixes, title, more user feedback, the usual --- src/main/java/com/MylesAndMore/tumble/Game.java | 86 +++++++++++-------------- 1 file changed, 38 insertions(+), 48 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 5b594fa..ce27f66 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -5,6 +5,7 @@ import org.bukkit.*; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import javax.annotation.Nullable; import java.util.*; public class Game { @@ -112,7 +113,14 @@ public class Game { // 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)); - gameState = "running"; + // Wait 5s (50t) for the clients to load in + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { + // Display the "go!" title + displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1); + // Set gamemodes to survival + setGamemode(gamePlayers, GameMode.SURVIVAL); + gameState = "running"; + }, 50); return true; } @@ -221,42 +229,21 @@ public class Game { } } - // THIS METHOD IS DEPRECATED!! - // It has been replaced by teleportPlayers(), I'm just leaving this just in case teleportPlayers() doesn't work out /** - private void sendPlayers() { - // Get the X, Y, and Z coords of that location - double x = gameSpawn.getX(); - double y = gameSpawn.getY(); - double z = gameSpawn.getZ(); - // Create Locations to scatter players around the first layer - // These are just edited off the original spawn location; - // they assume that the first layer has a radius of 17 blocks (it always will w/ the current generator code) - List scatterLocations = new ArrayList<>(); - scatterLocations.addAll(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 location list so players don't always spawn in the same location (basically, actually scatter the locations) - Collections.shuffle(scatterLocations); - // 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 (Player aPlayer : TumbleManager.getPlayersInLobby()) { - // Get a singular location from the scatter list - Location aLocation = scatterLocations.get(0); - // Teleport that player to that scatter location - aPlayer.teleport(aLocation); - // Remove that location from the list so that it cannot be used again - scatterLocations.remove(0); + * 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 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); } } - */ /** * Teleports a list of players to the specified scatter locations in the gameWorld @@ -304,29 +291,32 @@ public class Game { else { // Re-generate layers generateLayers(gameType); - // Re-scatter players - scatterPlayers(gamePlayers); - // Set their gamemodes to survival - setGamemode(gamePlayers, GameMode.SURVIVAL); + Bukkit.getServer().broadcastMessage(ChatColor.BLUE + "A new round will begin in ten seconds!"); + // Wait 10s (100t) for tp method + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { + // Re-scatter players + scatterPlayers(gamePlayers); + displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1); + // Set their gamemodes to survival + setGamemode(gamePlayers, GameMode.SURVIVAL); + }, 200); } } private void gameEnd(Player winner) { // Announce win Bukkit.getServer().broadcastMessage(ChatColor.GOLD + winner.getName() + " has won the game!"); - Bukkit.getServer().broadcastMessage(ChatColor.GREEN + "Teleporting in five seconds..."); + Bukkit.getServer().broadcastMessage(ChatColor.BLUE + "Teleporting back in five seconds..."); // Wait 5s (100t), then - Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), new Runnable() { - @Override - public void run() { - // Set their gamemodes to survival - setGamemode(gamePlayers, GameMode.SURVIVAL); - // Send all players back to lobby (spawn) - for (Player aPlayer : gamePlayers) { - aPlayer.teleport(Bukkit.getWorld(TumbleManager.getLobbyWorld()).getSpawnLocation()); - } + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { + // Set their gamemodes to survival + setGamemode(gamePlayers, GameMode.SURVIVAL); + // Send all players back to lobby (spawn) + for (Player aPlayer : gamePlayers) { + aPlayer.teleport(Bukkit.getWorld(TumbleManager.getLobbyWorld()).getSpawnLocation()); } }, 100); + gameState = "complete"; } } -- cgit v1.2.3 From 135a411985ba67f45951c90f67d6c3730f133b0d Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Wed, 7 Dec 2022 13:58:52 +0000 Subject: add immediate respawn to the gameWorld on link --- src/main/java/com/MylesAndMore/tumble/commands/SetWorldConfig.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/MylesAndMore/tumble/commands/SetWorldConfig.java b/src/main/java/com/MylesAndMore/tumble/commands/SetWorldConfig.java index d27a5a8..74eaf0d 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,8 @@ 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); 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!"); } -- cgit v1.2.3 From 728cce24b86b2a90bc159bd650eb73e902071505 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Wed, 7 Dec 2022 19:17:27 +0000 Subject: parity and other gameplay changes now uses titles (mostly) instead of broadcast text when broadcast text is used, it is only sent to the game's players a few sounds have been added --- src/main/java/com/MylesAndMore/tumble/Game.java | 37 ++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index ce27f66..d3234a1 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -4,6 +4,7 @@ import com.MylesAndMore.tumble.api.Generator; import org.bukkit.*; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; import java.util.*; @@ -117,6 +118,7 @@ public class Game { Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { // Display the "go!" title displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1); + playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 1, 2); // Set gamemodes to survival setGamemode(gamePlayers, GameMode.SURVIVAL); gameState = "running"; @@ -245,6 +247,31 @@ public class Game { } } + /** + * Displays a message to a provided list of players + * @param players The player list for which to send the message to + * @param message The provided message (String format) + */ + private void displayMessage(List players, String message) { + for (Player aPlayer : players) { + aPlayer.sendMessage(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 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 @@ -280,23 +307,25 @@ public class Game { private void roundEnd(Player winner) { // Set the wins of the player to their current # of wins + 1 gameWins.set(gamePlayers.indexOf(winner), (gameWins.get(gamePlayers.indexOf(winner)) + 1)); - Bukkit.getServer().broadcastMessage(ChatColor.GREEN + winner.getName() + " has won the round!"); // Clear old layers (as a fill command, this would be /fill ~-20 ~-4 ~-20 ~20 ~ ~20 relative to spawn) Generator.generateCuboid(new Location(gameSpawn.getWorld(), gameSpawn.getX() - 20, gameSpawn.getY() - 4, gameSpawn.getZ() - 20), new Location(gameSpawn.getWorld(), gameSpawn.getX() + 20, gameSpawn.getY(), gameSpawn.getZ() + 20), Material.AIR); + playSound(gamePlayers, Sound.ENTITY_ELDER_GUARDIAN_CURSE, SoundCategory.HOSTILE, 1, 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 { + displayTitles(gamePlayers, ChatColor.RED + "Round over!", ChatColor.GOLD + winner.getName() + " has won the round!", 2, 20, 2); // Re-generate layers generateLayers(gameType); - Bukkit.getServer().broadcastMessage(ChatColor.BLUE + "A new round will begin in ten seconds!"); + displayMessage(gamePlayers, ChatColor.BLUE + "A new round will begin in ten seconds!"); // Wait 10s (100t) for tp method Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { // Re-scatter players scatterPlayers(gamePlayers); displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1); + playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 1, 2); // Set their gamemodes to survival setGamemode(gamePlayers, GameMode.SURVIVAL); }, 200); @@ -305,8 +334,8 @@ public class Game { private void gameEnd(Player winner) { // Announce win - Bukkit.getServer().broadcastMessage(ChatColor.GOLD + winner.getName() + " has won the game!"); - Bukkit.getServer().broadcastMessage(ChatColor.BLUE + "Teleporting back in five seconds..."); + displayTitles(gamePlayers, ChatColor.RED + "Game over!", ChatColor.GOLD + winner.getName() + " has won the game!", 4, 40, 2); + displayMessage(gamePlayers, ChatColor.BLUE + "Teleporting back in five seconds..."); // Wait 5s (100t), then Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { // Set their gamemodes to survival -- cgit v1.2.3 From 1e9bd767570ab714d6007daebb4ee618a5ccdf79 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Wed, 7 Dec 2022 20:00:23 +0000 Subject: prevent players from moving before game begins --- README.md | 10 +++++----- src/main/java/com/MylesAndMore/tumble/EventListener.java | 11 ++++++++++- src/main/java/com/MylesAndMore/tumble/Game.java | 9 ++++----- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index fd89174..0f98959 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,12 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele ## game realism - [x] make the shovel in shovels mode not lose any durabilty -- [ ] make it so that you can't move until the game begins +- [x] make it so that you can't move until the game begins - [ ] make the game blocks breakable very fast, but **not instantly--very important for balancing!!** - [ ] add infinite snowballs in the gamemanager for tumble mode -- [ ] make it so that you can't remove any of the game items from your inventory +- [x] make it so that you can't remove any of the game items from your inventory - [ ] make snowballs actually break blocks (duh) -- [ ] make the randomized mode logic +- [x] make the randomized mode logic - [ ] set some limits on the spectator mode in-game; make it so they can't fly outside of the map ## game logic (fyi: very object-oriented) @@ -25,8 +25,8 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele - [x] make a Game class and object that we can initialize a new instance of with a gameType - [ ] within this game object, while games are running: - [ ] prevent players from joining/autojoining during - - [ ] keep track of when someone wins; start a new round when this happens - - [ ] keep track of how many wins each player has; end the game when a player reaches 3 + - [x] keep track of when someone wins; start a new round when this happens + - [x] keep track of how many wins each player has; end the game when a player reaches 3 - [ ] add a section in the config for a place to tp the winning player - [ ] add logic to do this diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index 4c3d154..bfe6767 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -13,6 +13,7 @@ import org.bukkit.event.entity.ProjectileLaunchEvent; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerItemDamageEvent; import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.inventory.ItemStack; @@ -86,7 +87,6 @@ public class EventListener implements Listener{ } } - @EventHandler public void PlayerDropItemEvent(PlayerDropItemEvent event) { // When an item is dropped, make sure there is a defined gameWorld @@ -98,6 +98,15 @@ public class EventListener implements Listener{ } } } + + @EventHandler + public void PlayerMoveEvent(PlayerMoveEvent event) { + // 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); + } + } } diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index d3234a1..1b8227e 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -114,7 +114,7 @@ public class Game { // 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 (50t) for the clients to load in + // Wait 5s (100t) for the clients to load in Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { // Display the "go!" title displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1); @@ -122,7 +122,7 @@ public class Game { // Set gamemodes to survival setGamemode(gamePlayers, GameMode.SURVIVAL); gameState = "running"; - }, 50); + }, 100); return true; } @@ -336,7 +336,7 @@ public class Game { // Announce win displayTitles(gamePlayers, ChatColor.RED + "Game over!", ChatColor.GOLD + winner.getName() + " has won the game!", 4, 40, 2); displayMessage(gamePlayers, ChatColor.BLUE + "Teleporting back in five seconds..."); - // Wait 5s (100t), then + // Wait 10s (200t), then Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { // Set their gamemodes to survival setGamemode(gamePlayers, GameMode.SURVIVAL); @@ -344,8 +344,7 @@ public class Game { for (Player aPlayer : gamePlayers) { aPlayer.teleport(Bukkit.getWorld(TumbleManager.getLobbyWorld()).getSpawnLocation()); } - }, 100); + }, 200); gameState = "complete"; } - } -- cgit v1.2.3 From 8a1072641f30af8c06361a03a302321822c3ce7f Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Wed, 7 Dec 2022 20:14:25 +0000 Subject: prevent players from joining during a game --- README.md | 2 +- .../com/MylesAndMore/tumble/EventListener.java | 1 - src/main/java/com/MylesAndMore/tumble/Game.java | 121 +++++++++++---------- 3 files changed, 66 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index 0f98959..baa83c6 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele - [x] make a Game class and object that we can initialize a new instance of with a gameType - [ ] within this game object, while games are running: - - [ ] prevent players from joining/autojoining during + - [x] prevent players from joining/autojoining during - [x] keep track of when someone wins; start a new round when this happens - [x] keep track of how many wins each player has; end the game when a player reaches 3 - [ ] add a section in the config for a place to tp the winning player diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index bfe6767..d1a60ad 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -94,7 +94,6 @@ public class EventListener implements Listener{ // Then check if the item was dropped in the game world if (event.getPlayer().getWorld() == Bukkit.getWorld((TumbleManager.getGameWorld()))) { event.setCancelled(true); - } } } diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 1b8227e..439cbb1 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -60,69 +60,78 @@ public class Game { * @return true if the game succeeds creation, and false if not */ public boolean startGame() { - gameState = "starting"; - if (Objects.equals(TumbleManager.getGameType(), "shovels")) { - // Set the roundType to gameType since it won't change for this mode - roundType = gameType; - // Generate the correct layers for a Shovels game - // The else statement is just in case the generator fails; this command will fail - if (generateLayers(gameType)) { - // If the layer generation succeeds, give players diamond shovels - giveItems(lobbyPlayers, new ItemStack(Material.DIAMOND_SHOVEL)); - // Send all players from lobby to the game - scatterPlayers(lobbyPlayers); - // Keep in mind that after this runs, this command will complete and return true - } - else { - return false; - } + // 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 if (Objects.equals(TumbleManager.getGameType(), "snowballs")) { - roundType = gameType; - if (generateLayers(gameType)) { - giveItems(lobbyPlayers, new ItemStack(Material.SNOWBALL)); - scatterPlayers(lobbyPlayers); + else { + gameState = "starting"; + if (Objects.equals(TumbleManager.getGameType(), "shovels")) { + // Set the roundType to gameType since it won't change for this mode + roundType = gameType; + // Generate the correct layers for a Shovels game + // The else statement is just in case the generator fails; this command will fail + if (generateLayers(gameType)) { + // If the layer generation succeeds, give players diamond shovels + giveItems(lobbyPlayers, new ItemStack(Material.DIAMOND_SHOVEL)); + // Send all players from lobby to the game + scatterPlayers(lobbyPlayers); + // Keep in mind that after this runs, this command will complete and return true + } + else { + return false; + } } - else { - return false; + else if (Objects.equals(TumbleManager.getGameType(), "snowballs")) { + roundType = gameType; + if (generateLayers(gameType)) { + giveItems(lobbyPlayers, new ItemStack(Material.SNOWBALL)); + scatterPlayers(lobbyPlayers); + } + else { + return false; + } } - } - else if (Objects.equals(TumbleManager.getGameType(), "mixed")) { - // Mixed gamemode (choose random shovels/0 or snowballs/1) - if (Random.nextInt(2) == 0) { - roundType = "shovels"; - generateLayers("shovels"); - giveItems(lobbyPlayers, new ItemStack(Material.DIAMOND_SHOVEL)); - scatterPlayers(lobbyPlayers); + else if (Objects.equals(TumbleManager.getGameType(), "mixed")) { + // Mixed gamemode (choose random shovels/0 or snowballs/1) + if (Random.nextInt(2) == 0) { + roundType = "shovels"; + generateLayers("shovels"); + giveItems(lobbyPlayers, new ItemStack(Material.DIAMOND_SHOVEL)); + scatterPlayers(lobbyPlayers); + } + else { + roundType = "snowballs"; + generateLayers("snowballs"); + giveItems(lobbyPlayers, new ItemStack(Material.SNOWBALL)); + scatterPlayers(lobbyPlayers); + } } else { - roundType = "snowballs"; - generateLayers("snowballs"); - giveItems(lobbyPlayers, new ItemStack(Material.SNOWBALL)); - scatterPlayers(lobbyPlayers); + // 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(), () -> { + // Display the "go!" title + displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1); + playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 1, 2); + // Set gamemodes to survival + setGamemode(gamePlayers, GameMode.SURVIVAL); + gameState = "running"; + }, 100); } - else { - // 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(), () -> { - // Display the "go!" title - displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1); - playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 1, 2); - // Set gamemodes to survival - setGamemode(gamePlayers, GameMode.SURVIVAL); - gameState = "running"; - }, 100); return true; } -- cgit v1.2.3 From 0860c7913225943cd16f8a149ec9cf0b407ce359 Mon Sep 17 00:00:00 2001 From: Myles Date: Wed, 7 Dec 2022 19:06:55 -0600 Subject: bug fixes and duplicate game glitch fixed --- src/main/java/com/MylesAndMore/tumble/Game.java | 25 +++++++++++++--------- .../MylesAndMore/tumble/commands/StartGame.java | 16 +++++++++++--- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 439cbb1..117faff 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -318,33 +318,38 @@ public class Game { gameWins.set(gamePlayers.indexOf(winner), (gameWins.get(gamePlayers.indexOf(winner)) + 1)); // Clear old layers (as a fill command, this would be /fill ~-20 ~-4 ~-20 ~20 ~ ~20 relative to spawn) Generator.generateCuboid(new Location(gameSpawn.getWorld(), gameSpawn.getX() - 20, gameSpawn.getY() - 4, gameSpawn.getZ() - 20), new Location(gameSpawn.getWorld(), gameSpawn.getX() + 20, gameSpawn.getY(), gameSpawn.getZ() + 20), Material.AIR); - playSound(gamePlayers, Sound.ENTITY_ELDER_GUARDIAN_CURSE, SoundCategory.HOSTILE, 1, 1); + playSound(gamePlayers, Sound.BLOCK_NOTE_BLOCK_PLING, SoundCategory.BLOCKS, 5, 0); // 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 { - displayTitles(gamePlayers, ChatColor.RED + "Round over!", ChatColor.GOLD + winner.getName() + " has won the round!", 2, 20, 2); + displayTitles(gamePlayers, ChatColor.RED + "Round over!", ChatColor.GOLD + winner.getName() + " has won the round!", 5, 60, 5); // Re-generate layers generateLayers(gameType); displayMessage(gamePlayers, ChatColor.BLUE + "A new round will begin in ten seconds!"); - // Wait 10s (100t) for tp method + // Wait 5s (100t) for tp method Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { // Re-scatter players + gameState = "starting"; scatterPlayers(gamePlayers); - displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1); - playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 1, 2); - // Set their gamemodes to survival - setGamemode(gamePlayers, GameMode.SURVIVAL); - }, 200); + // Wait another 5s for game start + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { + displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1); + playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 1, 2); + // Set their gamemodes to survival + setGamemode(gamePlayers, GameMode.SURVIVAL); + gameState = "running"; + }, 100); + }, 100); } } private void gameEnd(Player winner) { // Announce win - displayTitles(gamePlayers, ChatColor.RED + "Game over!", ChatColor.GOLD + winner.getName() + " has won the game!", 4, 40, 2); - displayMessage(gamePlayers, ChatColor.BLUE + "Teleporting back in five seconds..."); + displayTitles(gamePlayers, ChatColor.RED + "Game over!", ChatColor.GOLD + winner.getName() + " has won the game!", 5, 60, 5); + displayMessage(gamePlayers, ChatColor.BLUE + "Teleporting back in ten seconds..."); // Wait 10s (200t), then Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { // Set their gamemodes to survival diff --git a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java index 2e531ef..5577173 100644 --- a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java +++ b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java @@ -7,6 +7,8 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; +import java.util.Objects; + public class StartGame implements CommandExecutor { public void startGame(CommandSender sender, String[] args) { // Check if sender has perms to run command @@ -17,14 +19,22 @@ public class StartGame implements CommandExecutor { if (TumbleManager.getPlayersInLobby().size() > 0) { // Check if there is a gameWorld specified in config if (TumbleManager.getGameWorld() != null) { - sender.sendMessage("Starting game, please wait."); // Use multiverse to load game world // If the load was successful, start game if (TumbleManager.getMVWorldManager().loadWorld(TumbleManager.getGameWorld())) { // Check which gamemode to initiate from the config file if (!Game.getGame().startGame()) { - // 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 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")); + } + sender.sendMessage(ChatColor.BLUE + "Starting game, please wait."); } } // If load was unsuccessful, give feedback -- cgit v1.2.3 From e8e547d0f559f330157eda2d44596c13932400cf Mon Sep 17 00:00:00 2001 From: Myles Date: Wed, 7 Dec 2022 19:36:12 -0600 Subject: wow I finally added a *core game mechanic*!11!! (blocks break when a snowball impacts them in the gameWorld) --- README.md | 20 +++++-------- .../com/MylesAndMore/tumble/EventListener.java | 34 ++++++++++++++++++++++ 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index baa83c6..7cc6990 100644 --- a/README.md +++ b/README.md @@ -14,25 +14,21 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele - [x] make the shovel in shovels mode not lose any durabilty - [x] make it so that you can't move until the game begins - [ ] make the game blocks breakable very fast, but **not instantly--very important for balancing!!** + - Basically, just set a "cooldown" on both snowballs and shovels--not a long one--but one at that - [ ] add infinite snowballs in the gamemanager for tumble mode - [x] make it so that you can't remove any of the game items from your inventory -- [ ] make snowballs actually break blocks (duh) +- [x] make snowballs actually break blocks (duh) - [x] make the randomized mode logic - [ ] set some limits on the spectator mode in-game; make it so they can't fly outside of the map -## game logic (fyi: very object-oriented) +## game logic - [x] make a Game class and object that we can initialize a new instance of with a gameType - - [ ] within this game object, while games are running: - - [x] prevent players from joining/autojoining during - - [x] keep track of when someone wins; start a new round when this happens - - [x] keep track of how many wins each player has; end the game when a player reaches 3 - - [ ] add a section in the config for a place to tp the winning player - - [ ] add logic to do this - -## game legitimacy (@MylesAndMore) - -- [ ] add some example layer generation and layer material types, from actual game @MylesAndMore +- [x] prevent players from joining/autojoining during a game +- [x] keep track of when someone wins; start a new round when this happens +- [x] keep track of how many wins each player has; end the game when a player reaches 3 + - [ ] add a section in the config for a place to tp the winning player + - [ ] add logic to do this ## configuration/customization diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index d1a60ad..00dbe07 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -8,7 +8,9 @@ import org.bukkit.entity.Player; import org.bukkit.entity.Snowball; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.entity.FoodLevelChangeEvent; import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.event.entity.ProjectileLaunchEvent; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerItemDamageEvent; @@ -87,6 +89,27 @@ public class EventListener implements Listener{ } } + @EventHandler + public void ProjectileHitEvent(ProjectileHitEvent event) { + // When a projectile hits, check to see if the gameWorld is null, + if (TumbleManager.getGameWorld() != null) { + // then 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 player) { + // then check if that block is within the game area, + if (event.getHitBlock().getLocation().distanceSquared(Bukkit.getWorld(TumbleManager.getGameWorld()).getSpawnLocation()) < 402) { + // then remove that block. + event.getHitBlock().setType(Material.AIR); + } + } + } + } + } + } + @EventHandler public void PlayerDropItemEvent(PlayerDropItemEvent event) { // When an item is dropped, make sure there is a defined gameWorld @@ -106,6 +129,17 @@ public class EventListener implements Listener{ event.setCancelled(true); } } + + @EventHandler + public void FoodLevelChangeEvent(FoodLevelChangeEvent event) { + // When someone's food level changes, check if the gameWorld is null, + if (TumbleManager.getGameWorld() != null) { + // then check if that happened in the gameWorld + if (event.getEntity().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) { + event.setCancelled(true); + } + } + } } -- cgit v1.2.3 From eec44e9903e3cb15449d9c1df41425e8063ee7f6 Mon Sep 17 00:00:00 2001 From: Myles Date: Wed, 7 Dec 2022 19:54:54 -0600 Subject: THE COUNTDOWN IS THE BEST THING I'VE ADDED --- src/main/java/com/MylesAndMore/tumble/Game.java | 48 +++++++++++++++++-------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 117faff..cb49443 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -124,12 +124,23 @@ public class Game { 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(), () -> { - // Display the "go!" title - displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1); - playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 1, 2); - // Set gamemodes to survival - setGamemode(gamePlayers, GameMode.SURVIVAL); - gameState = "running"; + // Begin the countdown sequence + playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 1, 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, 1, 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, 1, 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, 1, 2); + displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1); + setGamemode(gamePlayers, GameMode.SURVIVAL); + gameState = "running"; + }, 20); + }, 20); + }, 20); }, 100); } return true; @@ -328,20 +339,27 @@ public class Game { displayTitles(gamePlayers, ChatColor.RED + "Round over!", ChatColor.GOLD + winner.getName() + " has won the round!", 5, 60, 5); // Re-generate layers generateLayers(gameType); - displayMessage(gamePlayers, ChatColor.BLUE + "A new round will begin in ten seconds!"); // Wait 5s (100t) for tp method Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { // Re-scatter players gameState = "starting"; scatterPlayers(gamePlayers); - // Wait another 5s for game start + playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 1, 1); + displayTitles(gamePlayers, ChatColor.DARK_GREEN + "3", null, 3, 10, 7); Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { - displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1); - playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 1, 2); - // Set their gamemodes to survival - setGamemode(gamePlayers, GameMode.SURVIVAL); - gameState = "running"; - }, 100); + playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 1, 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, 1, 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, 1, 2); + displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1); + setGamemode(gamePlayers, GameMode.SURVIVAL); + gameState = "running"; + }, 20); + }, 20); + }, 20); }, 100); } } @@ -349,7 +367,7 @@ public class Game { private void gameEnd(Player winner) { // Announce win displayTitles(gamePlayers, ChatColor.RED + "Game over!", ChatColor.GOLD + winner.getName() + " has won the game!", 5, 60, 5); - displayMessage(gamePlayers, ChatColor.BLUE + "Teleporting back in ten seconds..."); + displayMessage(gamePlayers, ChatColor.BLUE + "Returning to lobby in ten seconds..."); // Wait 10s (200t), then Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { // Set their gamemodes to survival -- cgit v1.2.3 From 1a8b11f68e1e8089f5c145e4dc7335c296d5e6a4 Mon Sep 17 00:00:00 2001 From: Myles Date: Wed, 7 Dec 2022 21:12:39 -0600 Subject: I broke things (as usual) --- src/main/java/com/MylesAndMore/tumble/commands/StartGame.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java index 5577173..315219a 100644 --- a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java +++ b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java @@ -24,6 +24,7 @@ public class StartGame implements CommandExecutor { if (TumbleManager.getMVWorldManager().loadWorld(TumbleManager.getGameWorld())) { // Check which gamemode to initiate from the config file if (!Game.getGame().startGame()) { + sender.sendMessage(ChatColor.BLUE + "Starting game, please wait."); // 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!"); @@ -34,7 +35,6 @@ public class StartGame implements CommandExecutor { else { sender.sendMessage(ChatColor.RED + "Failed to recognize game of type " + ChatColor.GRAY + TumbleManager.getPlugin().getConfig().getString("gameMode")); } - sender.sendMessage(ChatColor.BLUE + "Starting game, please wait."); } } // If load was unsuccessful, give feedback -- cgit v1.2.3 From c7d259a122ebd8300d84914032e247a5cc4a7f01 Mon Sep 17 00:00:00 2001 From: Myles Date: Wed, 7 Dec 2022 21:13:33 -0600 Subject: add feature: seperate winning player tp --- README.md | 4 +- src/main/java/com/MylesAndMore/tumble/Game.java | 9 ++- src/main/java/com/MylesAndMore/tumble/Main.java | 1 + .../MylesAndMore/tumble/commands/SetWinnerLoc.java | 85 ++++++++++++++++++++++ src/main/resources/config.yml | 10 +++ src/main/resources/plugin.yml | 8 ++ 6 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/MylesAndMore/tumble/commands/SetWinnerLoc.java diff --git a/README.md b/README.md index 7cc6990..1a8306a 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,8 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele - [x] prevent players from joining/autojoining during a game - [x] keep track of when someone wins; start a new round when this happens - [x] keep track of how many wins each player has; end the game when a player reaches 3 - - [ ] add a section in the config for a place to tp the winning player - - [ ] add logic to do this + - [x] add a section in the config for a place to tp the winning player + - [x] add logic to do this ## configuration/customization diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index cb49443..f3c7ef4 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -370,8 +370,13 @@ public class Game { displayMessage(gamePlayers, ChatColor.BLUE + "Returning to lobby in ten seconds..."); // Wait 10s (200t), then Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { - // Set their gamemodes to survival - setGamemode(gamePlayers, GameMode.SURVIVAL); + // 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()); diff --git a/src/main/java/com/MylesAndMore/tumble/Main.java b/src/main/java/com/MylesAndMore/tumble/Main.java index 5c08907..04c8053 100644 --- a/src/main/java/com/MylesAndMore/tumble/Main.java +++ b/src/main/java/com/MylesAndMore/tumble/Main.java @@ -14,6 +14,7 @@ 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()); // Save the default config file (packaged in the JAR) this.saveDefaultConfig(); 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..8a76383 --- /dev/null +++ b/src/main/java/com/MylesAndMore/tumble/commands/SetWinnerLoc.java @@ -0,0 +1,85 @@ +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; + +import java.util.Objects; + +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) { + Location senderPos = ((Player) sender).getLocation(); + // if so, check if any of their locations are zero + if (!((Objects.equals(senderPos.getX(), "0") || Objects.equals(senderPos.getX(), "-0") || Objects.equals(senderPos.getY(), "0") || Objects.equals(senderPos.getY(), "-0") || Objects.equals(senderPos.getZ(), "0") || Objects.equals(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."); + } + } + // 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."); + return false; + } catch (Exception e){ + sender.sendMessage(ChatColor.RED + "Invalid input arguments."); + return false; + } + // 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/resources/config.yml b/src/main/resources/config.yml index a881556..0f059f2 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -10,6 +10,16 @@ permissionMessage: You do not have permission to perform this command! # Default is mixed gameMode: mixed +# Customize the place that the winner is teleported after a game ends +# This is an optional value +# Default is nothing +winnerTeleport: + # These coordinates cannot be zero! The teleport will fail if any of them are. + # Use something like 0.5 instead. + x: + y: + z: + # This tells the plugin which worlds it should use as the lobby/game worlds # Do NOT change unless you know what you're doing!! # Will be blank by default diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index dd24bcc..3dc3b90 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -22,6 +22,11 @@ commands: description: Force starts a Tumble match. usage: '§cUsage: /tumble:start' permission: start + winlocation: + description: Links the location to teleport the winning player of a game. + usage: '§cUsage: /tumble:winlocation ' + permission: winlocation + aliases: [win-location, winloc, win-loc] permissions: reload: description: Allows you to reload the plugin's config. @@ -32,3 +37,6 @@ permissions: start: description: Allows you to start a Tumble match. default: op + winlocation: + description: Allows you to link a win location. + default: op -- cgit v1.2.3 From 777f510256896bbf7cd73b6da7109b875ef6218e Mon Sep 17 00:00:00 2001 From: Myles Date: Wed, 7 Dec 2022 21:49:09 -0600 Subject: fix this random stacktrace I got I think it happens if the snowball despawns before hitting something? here's the stacktrace for future reference: [21:46:02 ERROR]: Could not pass event ProjectileHitEvent to tumble v0.0.1-SNAPSHOT java.lang.NullPointerException: Cannot invoke "org.bukkit.block.Block.getWorld()" because the return value of "org.bukkit.event.entity.ProjectileHitEvent.getHitBlock()" is null at com.MylesAndMore.tumble.EventListener.ProjectileHitEvent(EventListener.java:97) ~[tumble-0.0.1-SNAPSHOT.jar:?] at com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor22.execute(Unknown Source) ~[?:?] at org.bukkit.plugin.EventExecutor.lambda$create$1(EventExecutor.java:75) ~[paper-api-1.19.2-R0.1-SNAPSHOT.jar:?] at co.aikar.timings.TimedEventExecutor.execute(TimedEventExecutor.java:80) ~[paper-api-1.19.2-R0.1-SNAPSHOT.jar:git-Paper-235] at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:70) ~[paper-api-1.19.2-R0.1-SNAPSHOT.jar:?] at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:670) ~[paper-api-1.19.2-R0.1-SNAPSHOT.jar:?] at org.bukkit.craftbukkit.v1_19_R1.event.CraftEventFactory.callProjectileHitEvent(CraftEventFactory.java:1423) ~[paper-1.19.2.jar:git-Paper-235] at net.minecraft.world.entity.projectile.Projectile.preOnHit(Projectile.java:169) ~[?:?] at net.minecraft.world.entity.projectile.ThrowableProjectile.tick(ThrowableProjectile.java:79) ~[?:?] at net.minecraft.server.level.ServerLevel.tickNonPassenger(ServerLevel.java:1192) ~[?:?] at net.minecraft.world.level.Level.guardEntityTick(Level.java:897) ~[?:?] at net.minecraft.server.level.ServerLevel.lambda$tick$6(ServerLevel.java:730) ~[?:?] at net.minecraft.world.level.entity.EntityTickList.forEach(EntityTickList.java:42) ~[paper-1.19.2.jar:git-Paper-235] at net.minecraft.server.level.ServerLevel.tick(ServerLevel.java:710) ~[?:?] at net.minecraft.server.MinecraftServer.tickChildren(MinecraftServer.java:1535) ~[paper-1.19.2.jar:git-Paper-235] at net.minecraft.server.dedicated.DedicatedServer.tickChildren(DedicatedServer.java:446) ~[paper-1.19.2.jar:git-Paper-235] at net.minecraft.server.MinecraftServer.tickServer(MinecraftServer.java:1397) ~[paper-1.19.2.jar:git-Paper-235] at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1173) ~[paper-1.19.2.jar:git-Paper-235] at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:305) ~[paper-1.19.2.jar:git-Paper-235] at java.lang.Thread.run(Thread.java:833) ~[?:?] --- src/main/java/com/MylesAndMore/tumble/EventListener.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index 00dbe07..a0f5061 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -107,6 +107,9 @@ public class EventListener implements Listener{ } } } + else if (event.getHitBlock().getWorld() == null) { + event.setCancelled(true); + } } } -- cgit v1.2.3 From 102627d4b28589676ddccc359a9ecd0dffa13f85 Mon Sep 17 00:00:00 2001 From: Myles Date: Wed, 7 Dec 2022 21:54:26 -0600 Subject: rewrite basically an entire method (rip my sanity) you can now specify what type of game in the cmd and not just the config file (although the config file still works) but now testing should be easier! and also flexibility is cool I wonder how many bugs this will cause in the future... --- src/main/java/com/MylesAndMore/tumble/Game.java | 57 ++++++++++------------ .../MylesAndMore/tumble/commands/StartGame.java | 40 ++++++++++----- 2 files changed, 54 insertions(+), 43 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index f3c7ef4..2106e9a 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -30,8 +30,6 @@ public class Game { // Define local game vars - // The gameType keeps the current game type (shocker) - private static String gameType = TumbleManager.getGameType(); // The gameState keeps the current state of the game (I'm so creative, I know) private String gameState; // Define a variable for the roundType @@ -57,9 +55,10 @@ public class Game { /** * Creates a new Game + * @param type The type of game * @return true if the game succeeds creation, and false if not */ - public boolean startGame() { + 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; @@ -68,15 +67,14 @@ public class Game { return false; } else { - gameState = "starting"; - if (Objects.equals(TumbleManager.getGameType(), "shovels")) { + // Define the gameType + if (Objects.equals(type, "shovels")) { + gameState = "starting"; // Set the roundType to gameType since it won't change for this mode - roundType = gameType; + roundType = type; // Generate the correct layers for a Shovels game // The else statement is just in case the generator fails; this command will fail - if (generateLayers(gameType)) { - // If the layer generation succeeds, give players diamond shovels - giveItems(lobbyPlayers, new ItemStack(Material.DIAMOND_SHOVEL)); + if (generateLayers(type)) { // Send all players from lobby to the game scatterPlayers(lobbyPlayers); // Keep in mind that after this runs, this command will complete and return true @@ -85,29 +83,24 @@ public class Game { return false; } } - else if (Objects.equals(TumbleManager.getGameType(), "snowballs")) { - roundType = gameType; - if (generateLayers(gameType)) { - giveItems(lobbyPlayers, new ItemStack(Material.SNOWBALL)); + else if (Objects.equals(type, "snowballs")) { + gameState = "starting"; + roundType = type; + if (generateLayers(type)) { scatterPlayers(lobbyPlayers); } else { return false; } } - else if (Objects.equals(TumbleManager.getGameType(), "mixed")) { - // Mixed gamemode (choose random shovels/0 or snowballs/1) - if (Random.nextInt(2) == 0) { - roundType = "shovels"; - generateLayers("shovels"); - giveItems(lobbyPlayers, new ItemStack(Material.DIAMOND_SHOVEL)); + else if (Objects.equals(type, "mixed")) { + gameState = "starting"; + roundType = type; + if (generateLayers(type)) { scatterPlayers(lobbyPlayers); } else { - roundType = "snowballs"; - generateLayers("snowballs"); - giveItems(lobbyPlayers, new ItemStack(Material.SNOWBALL)); - scatterPlayers(lobbyPlayers); + return false; } } else { @@ -141,7 +134,7 @@ public class Game { }, 20); }, 20); }, 20); - }, 100); + }, 100); } return true; } @@ -183,13 +176,13 @@ public class Game { /** * Generates the layers in the gameWorld for a certain gameType - * @param gameType can be either "shovels", "snowballs", or "mixed", anything else will fail generation + * @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 gameType) { + 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(roundType, "shovels")) { + if (Objects.equals(type, "shovels")) { layer.setY(layer.getY() - 1); Generator.generateLayer(layer, 17, 1, Material.SNOW_BLOCK); Generator.generateLayer(layer, 13, 1, Material.AIR); @@ -199,9 +192,9 @@ public class Game { Generator.generateLayer(layer, 4, 1, Material.PODZOL); layer.setY(layer.getY() + 2); Generator.generateLayer(layer, 4, 2, Material.TALL_GRASS); - roundType = "shovels"; + giveItems(lobbyPlayers, new ItemStack(Material.DIAMOND_SHOVEL)); } - else if (Objects.equals(roundType, "snowballs")) { + else if (Objects.equals(type, "snowballs")) { layer.setY(layer.getY() - 1); Generator.generateLayer(layer, 17, 1, Material.COAL_ORE); Generator.generateLayer(layer, 13, 1, Material.AIR); @@ -210,9 +203,9 @@ public class Game { Generator.generateLayer(layer, 4, 1, Material.AIR); layer.setY(layer.getY() - 1); Generator.generateLayer(layer, 4, 1, Material.LIME_GLAZED_TERRACOTTA); - roundType = "snowballs"; + giveItems(lobbyPlayers, new ItemStack(Material.SNOWBALL)); } - else if (Objects.equals(gameType, "mixed")) { + else if (Objects.equals(type, "mixed")) { // Randomly select either shovels or snowballs and re-run the method if (Random.nextInt(2) == 0) { generateLayers("shovels"); @@ -338,7 +331,7 @@ public class Game { else { displayTitles(gamePlayers, ChatColor.RED + "Round over!", ChatColor.GOLD + winner.getName() + " has won the round!", 5, 60, 5); // Re-generate layers - generateLayers(gameType); + generateLayers(roundType); // Wait 5s (100t) for tp method Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { // Re-scatter players diff --git a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java index 315219a..17d2a34 100644 --- a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java +++ b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java @@ -19,21 +19,39 @@ public class StartGame implements CommandExecutor { if (TumbleManager.getPlayersInLobby().size() > 0) { // Check if there is a gameWorld specified in config if (TumbleManager.getGameWorld() != null) { + sender.sendMessage(ChatColor.BLUE + "Starting game, please wait."); // Use multiverse to load game world // If the load was successful, start game if (TumbleManager.getMVWorldManager().loadWorld(TumbleManager.getGameWorld())) { - // Check which gamemode to initiate from the config file - if (!Game.getGame().startGame()) { - sender.sendMessage(ChatColor.BLUE + "Starting game, please wait."); - // 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!"); + // 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")); + } } - 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]); + } } } } -- cgit v1.2.3 From fe5802a8e8eeb3199d05e995384b8e13bfce9784 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Thu, 8 Dec 2022 14:00:22 +0000 Subject: update start command usage --- src/main/resources/plugin.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 3dc3b90..315797f 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ main: com.MylesAndMore.tumble.Main name: tumble version: 0.0.1-SNAPSHOT -description: 'A Minecraft: Java Edition plugin recreating the Tumble minigame from Minecraft: Xbox 360 Edition.' +description: 'A Minecraft: Java Edition plugin recreating the Tumble minigame from Minecraft Legacy Console Edition.' api-version: 1.19 load: STARTUP author: MylesAndMore @@ -15,12 +15,12 @@ commands: permission: reload link: description: Links a world on the server as a lobby/game world. - usage: '§cUsage: /tumble:link lobby|game' + usage: '§cUsage: /tumble:link (lobby|game)' permission: link aliases: [linkworld, link-world] start: - description: Force starts a Tumble match. - usage: '§cUsage: /tumble:start' + description: Force starts a Tumble match with an optional game type. + usage: '§cUsage: /tumble:start [gametype]' permission: start winlocation: description: Links the location to teleport the winning player of a game. -- cgit v1.2.3 From 7c669404f8d7cdfc68ead2dd9c8128f627fadd4f Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Thu, 8 Dec 2022 17:07:12 +0000 Subject: remove deprecated startGame method in command --- src/main/java/com/MylesAndMore/tumble/commands/StartGame.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java index 17d2a34..46ca6ce 100644 --- a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java +++ b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java @@ -10,7 +10,8 @@ import org.bukkit.command.CommandSender; import java.util.Objects; public class StartGame implements CommandExecutor { - 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 @@ -81,11 +82,6 @@ public class StartGame implements CommandExecutor { else { sender.sendMessage(ChatColor.RED + TumbleManager.getPermissionMessage()); } - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - startGame(sender, args); return true; } } -- cgit v1.2.3 From f53fff2ac0b4dcff796a8b2e318c1725fd298a73 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Thu, 8 Dec 2022 17:18:24 +0000 Subject: add even *more* things to do (yay!!) --- README.md | 10 ++++++++-- src/main/java/com/MylesAndMore/tumble/Game.java | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1a8306a..7ac10e1 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,10 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele - [ ] layers should be able to generate w/ "clumps" of blocks; instead of only one material as a whole - [ ] the clump size should be customizable (for later); be able to set a min/max val and it will choose randomly per each clump (not in config file yet, just internally) - - PLEASE make a new class for this and make use of the generator if you can! +- [ ] make shovels generation actually work properly + - make different types of platforms (square, circle, multi-tiered, etc.); still should be pseudo-random +- [ ] make snowballs generation actually work properly (shocker) + - make three layers generate (same layer types as shovels, just multiple of them) ## game realism @@ -20,8 +23,11 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele - [x] make snowballs actually break blocks (duh) - [x] make the randomized mode logic - [ ] set some limits on the spectator mode in-game; make it so they can't fly outside of the map +- [ ] make it so rounds end in a draw after 5m +- [ ] make it so that players get snowballs instead of shovels in shovels rounds after 2m 30s +- [ ] remove snowball knockback -## game logic +## game logic - [x] make a Game class and object that we can initialize a new instance of with a gameType - [x] prevent players from joining/autojoining during a game diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 2106e9a..836f31a 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -192,7 +192,7 @@ public class Game { Generator.generateLayer(layer, 4, 1, Material.PODZOL); layer.setY(layer.getY() + 2); Generator.generateLayer(layer, 4, 2, Material.TALL_GRASS); - giveItems(lobbyPlayers, new ItemStack(Material.DIAMOND_SHOVEL)); + giveItems(lobbyPlayers, new ItemStack(Material.IRON_SHOVEL)); } else if (Objects.equals(type, "snowballs")) { layer.setY(layer.getY() - 1); -- cgit v1.2.3 From 2c741f101323ddadcf00a6414c0621f275866083 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Thu, 8 Dec 2022 17:25:59 +0000 Subject: convert chat message to actionbar --- src/main/java/com/MylesAndMore/tumble/Game.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 836f31a..c4d5c1f 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -1,6 +1,10 @@ package com.MylesAndMore.tumble; import com.MylesAndMore.tumble.api.Generator; + +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; + import org.bukkit.*; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -261,13 +265,13 @@ public class Game { } /** - * Displays a message to a provided list of players - * @param players The player list for which to send the message to + * 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 displayMessage(List players, String message) { + private void displayActionbar(List players, String message) { for (Player aPlayer : players) { - aPlayer.sendMessage(message); + aPlayer.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message)); } } @@ -360,7 +364,7 @@ public class Game { private void gameEnd(Player winner) { // Announce win displayTitles(gamePlayers, ChatColor.RED + "Game over!", ChatColor.GOLD + winner.getName() + " has won the game!", 5, 60, 5); - displayMessage(gamePlayers, ChatColor.BLUE + "Returning to lobby in ten seconds..."); + 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 -- cgit v1.2.3 From 2b457214a44b8e8058b816d057ac3f469ea1c256 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Thu, 8 Dec 2022 17:31:57 +0000 Subject: Myles is a bugpipe --- src/main/java/com/MylesAndMore/tumble/commands/SetWinnerLoc.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/commands/SetWinnerLoc.java b/src/main/java/com/MylesAndMore/tumble/commands/SetWinnerLoc.java index 8a76383..88c4b74 100644 --- a/src/main/java/com/MylesAndMore/tumble/commands/SetWinnerLoc.java +++ b/src/main/java/com/MylesAndMore/tumble/commands/SetWinnerLoc.java @@ -9,8 +9,6 @@ import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; -import java.util.Objects; - public class SetWinnerLoc implements CommandExecutor { @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { @@ -22,7 +20,7 @@ public class SetWinnerLoc implements CommandExecutor { if (sender instanceof Player) { Location senderPos = ((Player) sender).getLocation(); // if so, check if any of their locations are zero - if (!((Objects.equals(senderPos.getX(), "0") || Objects.equals(senderPos.getX(), "-0") || Objects.equals(senderPos.getY(), "0") || Objects.equals(senderPos.getY(), "-0") || Objects.equals(senderPos.getZ(), "0") || Objects.equals(senderPos.getZ(), "-0")))) { + 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()); -- cgit v1.2.3 From fe547e5b0767616d7ea1b4f94c57566589dbf4c3 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Thu, 8 Dec 2022 17:48:04 +0000 Subject: allow players to specify args for winLoc --- .../MylesAndMore/tumble/commands/SetWinnerLoc.java | 60 +++++++++++++++++----- src/main/resources/plugin.yml | 2 +- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/commands/SetWinnerLoc.java b/src/main/java/com/MylesAndMore/tumble/commands/SetWinnerLoc.java index 88c4b74..ec145d1 100644 --- a/src/main/java/com/MylesAndMore/tumble/commands/SetWinnerLoc.java +++ b/src/main/java/com/MylesAndMore/tumble/commands/SetWinnerLoc.java @@ -18,20 +18,54 @@ public class SetWinnerLoc implements CommandExecutor { if (TumbleManager.getLobbyWorld() != null) { // Check if the sender is a player if (sender instanceof Player) { - 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."); + // 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 { - sender.sendMessage(ChatColor.RED + "Your coordinates cannot be zero!"); - sender.sendMessage(ChatColor.RED + "Use something like 0.5 (the middle of the block) instead."); + return false; } } // Check if the sender is the console @@ -47,10 +81,8 @@ public class SetWinnerLoc implements CommandExecutor { args2 = Double.parseDouble(args[2]); } catch (NumberFormatException nfe){ sender.sendMessage(ChatColor.RED + "Input arguments must be valid numbers."); - return false; } catch (Exception e){ sender.sendMessage(ChatColor.RED + "Invalid input arguments."); - return false; } // 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))) { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 315797f..7066a27 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -24,7 +24,7 @@ commands: permission: start winlocation: description: Links the location to teleport the winning player of a game. - usage: '§cUsage: /tumble:winlocation ' + usage: '§cUsage: /tumble:winlocation [x] [y] [z]' permission: winlocation aliases: [win-location, winloc, win-loc] permissions: -- cgit v1.2.3 From 08189436cff46ecd50979bc0d70a3ccf026ec00d Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Thu, 8 Dec 2022 18:28:46 +0000 Subject: add autostart config and command --- README.md | 6 +- src/main/java/com/MylesAndMore/tumble/Main.java | 1 + .../MylesAndMore/tumble/commands/SetAutoStart.java | 79 ++++++++++++++++++++++ src/main/resources/config.yml | 26 ++++--- src/main/resources/plugin.yml | 10 ++- 5 files changed, 107 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/MylesAndMore/tumble/commands/SetAutoStart.java diff --git a/README.md b/README.md index 7ac10e1..97936bc 100644 --- a/README.md +++ b/README.md @@ -38,9 +38,9 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele ## configuration/customization -- [ ] add two configs where you can: - - [ ] set if you want the game to auto-start - - [ ] set the amt of players you want the game to auto-start at +- [x] add two configs where you can: + - [x] set if you want the game to auto-start + - [x] set the amt of players you want the game to auto-start at - [ ] program the auto-start (just add an if statement on the PlayerJoin listener to run the StartGame method on a certain amt of players in the config) ## etc diff --git a/src/main/java/com/MylesAndMore/tumble/Main.java b/src/main/java/com/MylesAndMore/tumble/Main.java index 04c8053..a35a519 100644 --- a/src/main/java/com/MylesAndMore/tumble/Main.java +++ b/src/main/java/com/MylesAndMore/tumble/Main.java @@ -15,6 +15,7 @@ public class Main extends JavaPlugin{ 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(); 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..d64573c --- /dev/null +++ b/src/main/java/com/MylesAndMore/tumble/commands/SetAutoStart.java @@ -0,0 +1,79 @@ +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 player # argument and parse it into an int + int args0 = 0; + try { + args0 = Integer.parseInt(args[0]); + } catch (NumberFormatException nfe){ + sender.sendMessage(ChatColor.RED + "Player amount must be a valid number."); + } catch (Exception e){ + sender.sendMessage(ChatColor.RED + "Invalid player amount."); + } + // Check the amount of args entered + if (args.length == 2) { + // 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", args[1]); + TumbleManager.getPlugin().saveConfig(); + } + else if (Objects.equals(args[1], "disable")) { + TumbleManager.getPlugin().getConfig().set("autoStart.players", args0); + TumbleManager.getPlugin().getConfig().set("autoStart.enabled", args[1]); + TumbleManager.getPlugin().saveConfig(); + } + 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 + if ((args0 >= 2) && (args0 <= 8)) { + TumbleManager.getPlugin().getConfig().set("autoStart.players", args0); + TumbleManager.getPlugin().saveConfig(); + } + 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/resources/config.yml b/src/main/resources/config.yml index 0f059f2..6c5e0a6 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -10,19 +10,23 @@ permissionMessage: You do not have permission to perform this command! # Default is mixed gameMode: mixed +# Customize the auto start feature of Tumble +# Defaults are disabled and two players +# Players can be up to 8 +autoStart: + enabled: false + players: 2 + # Customize the place that the winner is teleported after a game ends -# This is an optional value -# Default is nothing -winnerTeleport: - # These coordinates cannot be zero! The teleport will fail if any of them are. - # Use something like 0.5 instead. - x: - y: - z: +# Keep in mind that these coordinates cannot be zero! The teleport will fail if any of them are; use something like 0.5 instead. +# These are optional values--defaults are nothing +winnerTeleport: + x: + y: + z: # This tells the plugin which worlds it should use as the lobby/game worlds # Do NOT change unless you know what you're doing!! # Will be blank by default -lobbyWorld: -# Game world -gameWorld: \ No newline at end of file +lobbyWorld: +gameWorld: \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 7066a27..ac394bf 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -20,13 +20,18 @@ commands: aliases: [linkworld, link-world] start: description: Force starts a Tumble match with an optional game type. - usage: '§cUsage: /tumble:start [gametype]' + usage: '§cUsage: /tumble:start [gameType]' permission: start winlocation: description: Links the location to teleport the winning player of a game. usage: '§cUsage: /tumble:winlocation [x] [y] [z]' permission: winlocation aliases: [win-location, winloc, win-loc] + autostart: + description: Configures the auto start functions of Tumble. + usage: '§cUsage: /tumble:autostart [enable|disable]' + permission: autostart + aliases: [auto-start] permissions: reload: description: Allows you to reload the plugin's config. @@ -40,3 +45,6 @@ permissions: winlocation: description: Allows you to link a win location. default: op + autostart: + description: Allows you to set the autostart details of Tumble. + default: op -- cgit v1.2.3 From 673659d38ae4ad90bf86ff94b798960b0e3199df Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Thu, 8 Dec 2022 20:06:40 +0000 Subject: update config defaults --- src/main/resources/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 6c5e0a6..6a9f62d 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,6 +1,6 @@ # Hides join/leave messages in public chat # Default is true -hideJoinLeaveMessages: true +hideJoinLeaveMessages: false # Customize the message that displays when the player does not have permission to execute a command from this plugin permissionMessage: You do not have permission to perform this command! -- cgit v1.2.3 From 126b83f1ca45457dc1c9e08c1d0fc30b4fc8b88d Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Thu, 8 Dec 2022 20:53:57 +0000 Subject: program autostart logic --- README.md | 2 +- .../java/com/MylesAndMore/tumble/EventListener.java | 18 ++++++++++++++++++ src/main/java/com/MylesAndMore/tumble/Game.java | 21 ++++++++++++++++++++- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 97936bc..84fb55e 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele - [x] add two configs where you can: - [x] set if you want the game to auto-start - [x] set the amt of players you want the game to auto-start at - - [ ] program the auto-start (just add an if statement on the PlayerJoin listener to run the StartGame method on a certain amt of players in the config) + - [x] program the auto-start (just add an if statement on the PlayerJoin listener to run the StartGame method on a certain amt of players in the config) ## etc diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index a0f5061..8f9ab25 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -35,6 +35,14 @@ public class EventListener implements Listener{ // 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 (Bukkit.getWorld(TumbleManager.getGameWorld()).getPlayers().size() == TumbleManager.getPlugin().getConfig().getInt("autoStart.players")) { + // The autoStart should begin; pass this to the Game + Game.getGame().autoStart(); + } + } } } @@ -46,6 +54,16 @@ public class EventListener implements Listener{ if (TumbleManager.getPlugin().getConfig().getBoolean("hideJoinLeaveMessages")) { event.setQuitMessage(null); } + // Check if a player left in the lobbyWorld + if (TumbleManager.getLobbyWorld() != null) { + 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 + Bukkit.getServer().getScheduler().cancelTask(Game.getGame().getAutoStartID()); + } + } + } } @EventHandler diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index c4d5c1f..8099c80 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -38,6 +38,8 @@ public class Game { private String gameState; // Define a variable for the roundType private String roundType; + // Define a variable for the autostart PID + private int autoStartID; // Initialize a new instance of the Random class for use later private final Random Random = new Random(); @@ -143,6 +145,16 @@ public class Game { return true; } + public void autoStart() { + gameState = "waiting"; + displayActionbar(lobbyPlayers, ChatColor.GREEN + "Game will begin in 15 seconds!"); + playSound(lobbyPlayers, 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 + autoStartID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { + startGame(TumbleManager.getGameType()); + }, 300); + } + /** * This method should be called on the death of one of the Game's players * @param player The player who died @@ -171,10 +183,17 @@ public class Game { public String getRoundType() { return roundType; } /** - * @return The game's current state as a String ("starting", "running", "complete") + * @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 -- cgit v1.2.3 From 2d7de58b65fb7ecdd7c784707dbe2a39fa3d6e27 Mon Sep 17 00:00:00 2001 From: Myles Date: Thu, 8 Dec 2022 20:04:41 -0600 Subject: fix (most of) the bugs --- .../com/MylesAndMore/tumble/EventListener.java | 32 ++++++++-- src/main/java/com/MylesAndMore/tumble/Game.java | 39 +++++++++--- .../MylesAndMore/tumble/commands/SetAutoStart.java | 41 ++++++++---- .../MylesAndMore/tumble/commands/StartGame.java | 74 ++++++++++++---------- 4 files changed, 126 insertions(+), 60 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index 8f9ab25..7d07ab4 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -12,11 +12,7 @@ import org.bukkit.event.entity.FoodLevelChangeEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.event.entity.ProjectileLaunchEvent; -import org.bukkit.event.player.PlayerDropItemEvent; -import org.bukkit.event.player.PlayerItemDamageEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.*; import org.bukkit.inventory.ItemStack; public class EventListener implements Listener{ @@ -38,7 +34,7 @@ public class EventListener implements Listener{ // 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 (Bukkit.getWorld(TumbleManager.getGameWorld()).getPlayers().size() == TumbleManager.getPlugin().getConfig().getInt("autoStart.players")) { + if (TumbleManager.getPlayersInLobby().size() == TumbleManager.getPlugin().getConfig().getInt("autoStart.players")) { // The autoStart should begin; pass this to the Game Game.getGame().autoStart(); } @@ -46,6 +42,28 @@ public class EventListener implements Listener{ } } + @EventHandler + public void PlayerChangedWorldEvent(PlayerChangedWorldEvent event) { + // If the gameWorld and lobbyWorld is not null, then check + if (TumbleManager.getGameWorld() != null && TumbleManager.getLobbyWorld() != null) { + // if the player changed to the lobbyWorld, then + if (event.getPlayer().getWorld() == Bukkit.getWorld(TumbleManager.getLobbyWorld())) { + // run the autostart checks (from 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 @@ -60,7 +78,7 @@ public class EventListener implements Listener{ // Check if the game is in the process of autostarting if (Objects.equals(Game.getGame().getGameState(), "waiting")) { // Cancel the autostart - Bukkit.getServer().getScheduler().cancelTask(Game.getGame().getAutoStartID()); + Game.getGame().cancelStart(); } } } diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 8099c80..8eb9035 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -39,7 +39,7 @@ public class Game { // Define a variable for the roundType private String roundType; // Define a variable for the autostart PID - private int autoStartID; + private int autoStartID = -1; // Initialize a new instance of the Random class for use later private final Random Random = new Random(); @@ -73,6 +73,7 @@ public class Game { return false; } else { + Bukkit.getServer().broadcastMessage("game starting"); // Define the gameType if (Objects.equals(type, "shovels")) { gameState = "starting"; @@ -145,14 +146,36 @@ public class Game { return true; } + /** + * Initiates an automatic start of a Tumble game + */ public void autoStart() { - gameState = "waiting"; - displayActionbar(lobbyPlayers, ChatColor.GREEN + "Game will begin in 15 seconds!"); - playSound(lobbyPlayers, 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 - autoStartID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { - startGame(TumbleManager.getGameType()); - }, 300); + Bukkit.getServer().broadcastMessage("autoStart()"); + // Wait for the player to load in + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { + gameState = "waiting"; + displayActionbar(lobbyPlayers, ChatColor.GREEN + "Game will begin in 15 seconds!"); + playSound(lobbyPlayers, Sound.BLOCK_NOTE_BLOCK_CHIME, SoundCategory.BLOCKS, 1, 1); + Bukkit.getServer().broadcastMessage("title + sound"); + 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(), () -> { + Bukkit.getServer().broadcastMessage("startGame"); + startGame(TumbleManager.getGameType()); + }, 300); + }, 50); + } + + /** + * Cancels a "waiting" automatic start + */ + public void cancelStart() { + Bukkit.getServer().getScheduler().cancelTask(Game.getGame().getAutoStartID()); + displayActionbar(lobbyPlayers, ChatColor.RED + "Game start cancelled!"); + playSound(lobbyPlayers, Sound.BLOCK_NOTE_BLOCK_BASS, SoundCategory.BLOCKS, 1, 1); + Bukkit.getServer().broadcastMessage("game start cancelled"); + gameState = null; + autoStartID = -1; } /** diff --git a/src/main/java/com/MylesAndMore/tumble/commands/SetAutoStart.java b/src/main/java/com/MylesAndMore/tumble/commands/SetAutoStart.java index d64573c..0dcb4d9 100644 --- a/src/main/java/com/MylesAndMore/tumble/commands/SetAutoStart.java +++ b/src/main/java/com/MylesAndMore/tumble/commands/SetAutoStart.java @@ -1,6 +1,7 @@ package com.MylesAndMore.tumble.commands; import com.MylesAndMore.tumble.TumbleManager; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; @@ -16,30 +17,36 @@ public class SetAutoStart implements CommandExecutor{ // Check if game and lobby worlds are null if (TumbleManager.getGameWorld() != null) { if (TumbleManager.getLobbyWorld() != null) { - // Check the player # argument and parse it into an int - int args0 = 0; - try { - args0 = Integer.parseInt(args[0]); - } catch (NumberFormatException nfe){ - sender.sendMessage(ChatColor.RED + "Player amount must be a valid number."); - } catch (Exception e){ - sender.sendMessage(ChatColor.RED + "Invalid player amount."); - } // 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", args[1]); + 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", args[1]); + 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; @@ -51,9 +58,21 @@ public class SetAutoStart implements CommandExecutor{ } 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!"); diff --git a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java index 46ca6ce..d488fec 100644 --- a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java +++ b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java @@ -20,48 +20,54 @@ public class StartGame implements CommandExecutor { if (TumbleManager.getPlayersInLobby().size() > 0) { // Check if there is a gameWorld specified in config if (TumbleManager.getGameWorld() != null) { - sender.sendMessage(ChatColor.BLUE + "Starting game, 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!"); + // Check if a game is already pending to start + if (!Objects.equals(Game.getGame().getGameState(), "waiting")) { + sender.sendMessage(ChatColor.BLUE + "Starting game, 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")); + } } - 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 there was an argument for gameType, pass that into the startGame method + // 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.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]); - } - } + 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 -- cgit v1.2.3 From e6e1cbd384c676692c374cffff2abe7c5b32e3a0 Mon Sep 17 00:00:00 2001 From: Myles Date: Thu, 8 Dec 2022 22:06:31 -0600 Subject: I've been insulted ;-; --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 84fb55e..93d83c4 100644 --- a/README.md +++ b/README.md @@ -45,4 +45,6 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele ## etc +- [ ] refactor EventListener null checker code + - if (TumbleManager.getGameWorld() == null && TumbleManager.getLobbyWorld() == null) { return; } - [ ] add game music? but probably only for us; I feel like the og music must be copyrighted -- cgit v1.2.3 From f3ecc776931875fb36d775707d28c23ee047d188 Mon Sep 17 00:00:00 2001 From: Myles Date: Thu, 8 Dec 2022 22:06:40 -0600 Subject: LITERAL WEIRDEST BUG I HAVE EVER EXPERIENCED --- src/main/java/com/MylesAndMore/tumble/Game.java | 27 ++++++++++--------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 8eb9035..6d085df 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -47,8 +47,8 @@ public class Game { private final World gameWorld; private final Location gameSpawn; - // Make a list of the lobby's players for later - private List lobbyPlayers = TumbleManager.getPlayersInLobby(); +// // Make a list of the lobby's players for later +// private List lobbyPlayers = TumbleManager.getPlayersInLobby(); // Make a list of the game's players for later private List gamePlayers; // Make a list of the round's players @@ -73,7 +73,6 @@ public class Game { return false; } else { - Bukkit.getServer().broadcastMessage("game starting"); // Define the gameType if (Objects.equals(type, "shovels")) { gameState = "starting"; @@ -83,7 +82,7 @@ public class 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(lobbyPlayers); + scatterPlayers(TumbleManager.getPlayersInLobby()); // Keep in mind that after this runs, this command will complete and return true } else { @@ -94,7 +93,7 @@ public class Game { gameState = "starting"; roundType = type; if (generateLayers(type)) { - scatterPlayers(lobbyPlayers); + scatterPlayers(TumbleManager.getPlayersInLobby()); } else { return false; @@ -104,7 +103,7 @@ public class Game { gameState = "starting"; roundType = type; if (generateLayers(type)) { - scatterPlayers(lobbyPlayers); + scatterPlayers(TumbleManager.getPlayersInLobby()); } else { return false; @@ -150,17 +149,14 @@ public class Game { * Initiates an automatic start of a Tumble game */ public void autoStart() { - Bukkit.getServer().broadcastMessage("autoStart()"); // Wait for the player to load in Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { gameState = "waiting"; - displayActionbar(lobbyPlayers, ChatColor.GREEN + "Game will begin in 15 seconds!"); - playSound(lobbyPlayers, Sound.BLOCK_NOTE_BLOCK_CHIME, SoundCategory.BLOCKS, 1, 1); - Bukkit.getServer().broadcastMessage("title + sound"); + 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(), () -> { - Bukkit.getServer().broadcastMessage("startGame"); startGame(TumbleManager.getGameType()); }, 300); }, 50); @@ -171,9 +167,8 @@ public class Game { */ public void cancelStart() { Bukkit.getServer().getScheduler().cancelTask(Game.getGame().getAutoStartID()); - displayActionbar(lobbyPlayers, ChatColor.RED + "Game start cancelled!"); - playSound(lobbyPlayers, Sound.BLOCK_NOTE_BLOCK_BASS, SoundCategory.BLOCKS, 1, 1); - Bukkit.getServer().broadcastMessage("game start cancelled"); + displayActionbar(TumbleManager.getPlayersInLobby(), ChatColor.RED + "Game start cancelled!"); + playSound(TumbleManager.getPlayersInLobby(), Sound.BLOCK_NOTE_BLOCK_BASS, SoundCategory.BLOCKS, 1, 1); gameState = null; autoStartID = -1; } @@ -238,7 +233,7 @@ public class Game { Generator.generateLayer(layer, 4, 1, Material.PODZOL); layer.setY(layer.getY() + 2); Generator.generateLayer(layer, 4, 2, Material.TALL_GRASS); - giveItems(lobbyPlayers, new ItemStack(Material.IRON_SHOVEL)); + giveItems(TumbleManager.getPlayersInLobby(), new ItemStack(Material.IRON_SHOVEL)); } else if (Objects.equals(type, "snowballs")) { layer.setY(layer.getY() - 1); @@ -249,7 +244,7 @@ public class Game { Generator.generateLayer(layer, 4, 1, Material.AIR); layer.setY(layer.getY() - 1); Generator.generateLayer(layer, 4, 1, Material.LIME_GLAZED_TERRACOTTA); - giveItems(lobbyPlayers, new ItemStack(Material.SNOWBALL)); + giveItems(TumbleManager.getPlayersInLobby(), new ItemStack(Material.SNOWBALL)); } else if (Objects.equals(type, "mixed")) { // Randomly select either shovels or snowballs and re-run the method -- cgit v1.2.3 From f0a7cd62fb3759e0e196af23b711ff9513d3cd6e Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Fri, 9 Dec 2022 14:49:47 +0000 Subject: code is now insult-proof --- README.md | 2 +- .../com/MylesAndMore/tumble/EventListener.java | 199 +++++++++++---------- 2 files changed, 106 insertions(+), 95 deletions(-) diff --git a/README.md b/README.md index 93d83c4..04a4a38 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,6 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele ## etc -- [ ] refactor EventListener null checker code +- [x] refactor EventListener null checker code - if (TumbleManager.getGameWorld() == null && TumbleManager.getLobbyWorld() == null) { return; } - [ ] add game music? but probably only for us; I feel like the og music must be copyrighted diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index 7d07ab4..a5169c5 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -15,111 +15,120 @@ import org.bukkit.event.entity.ProjectileLaunchEvent; import org.bukkit.event.player.*; import org.bukkit.inventory.ItemStack; -public class EventListener implements Listener{ +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) + // 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()); - } - // 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(); - } + // Check if either of the worlds are not defined in config, if so, end + // This is to avoid NPEs and such + if (TumbleManager.getGameWorld() == null || TumbleManager.getLobbyWorld() == null) { + return; + } + // Check if the player joining is in the game world, if true then + if (event.getPlayer().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) { + // send them back to the lobby. + event.getPlayer().teleport(Bukkit.getWorld(TumbleManager.getLobbyWorld()).getSpawnLocation()); + } + // For auto-start function: check if the autoStart is enabled + if (TumbleManager.getPlugin().getConfig().getBoolean("autoStart.enabled")) { + // If so, check if the amount of players has been reached + if (TumbleManager.getPlayersInLobby().size() == TumbleManager.getPlugin().getConfig().getInt("autoStart.players")) { + // The autoStart should begin; pass this to the Game + Game.getGame().autoStart(); } } } @EventHandler public void PlayerChangedWorldEvent(PlayerChangedWorldEvent event) { - // If the gameWorld and lobbyWorld is not null, then check - if (TumbleManager.getGameWorld() != null && TumbleManager.getLobbyWorld() != null) { - // if the player changed to the lobbyWorld, then - if (event.getPlayer().getWorld() == Bukkit.getWorld(TumbleManager.getLobbyWorld())) { - // run the autostart checks (from above) - if (TumbleManager.getPlugin().getConfig().getBoolean("autoStart.enabled")) { - if (TumbleManager.getPlayersInLobby().size() == TumbleManager.getPlugin().getConfig().getInt("autoStart.players")) { - Game.getGame().autoStart(); - } + 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(); - } + } + // 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) + // 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); } - // Check if a player left in the lobbyWorld - if (TumbleManager.getLobbyWorld() != null) { - 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(); - } + 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) { - // On a PlayerDeathEvent, check to make sure the gameWorld is defined, - if (TumbleManager.getGameWorld() != null) { - // then 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()); - } + 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 ItemDamageEvent(PlayerItemDamageEvent event) { - // On a BlockBreakEvent, check to make sure there is a defined gameWorld - if (TumbleManager.getGameWorld() != null) { - // Then check to see if the block was broken in the gameWorld, - if (event.getPlayer().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) { - // If it was in the gameWorld, check if the roundType was shovels - if (Objects.equals(Game.getGame().getRoundType(), "shovels")) { - event.setCancelled(true); - } + if (TumbleManager.getGameWorld() == null) { + return; + } + // On a BlockBreakEvent, + // check to see if the block was broken in the gameWorld, + if (event.getPlayer().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) { + // If it was in the gameWorld, check if the roundType was shovels + if (Objects.equals(Game.getGame().getRoundType(), "shovels")) { + event.setCancelled(true); } } } @EventHandler public void ProjectileLaunchEvent(ProjectileLaunchEvent event) { - // When A projectile is launched, check to make sure there is a defined gameWorld - if (TumbleManager.getGameWorld() != null) { - // Then 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) { - player.getInventory().addItem(new ItemStack(Material.SNOWBALL,1)); - } + 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) { + player.getInventory().addItem(new ItemStack(Material.SNOWBALL, 1)); } } } @@ -127,22 +136,25 @@ public class EventListener implements Listener{ @EventHandler public void ProjectileHitEvent(ProjectileHitEvent event) { - // When a projectile hits, check to see if the gameWorld is null, - if (TumbleManager.getGameWorld() != null) { - // then 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 player) { - // then check if that block is within the game area, - if (event.getHitBlock().getLocation().distanceSquared(Bukkit.getWorld(TumbleManager.getGameWorld()).getSpawnLocation()) < 402) { - // then remove that block. - event.getHitBlock().setType(Material.AIR); - } + if (TumbleManager.getGameWorld() == 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 player) { + // then check if that block is within the game area, + if (event.getHitBlock().getLocation().distanceSquared( + Bukkit.getWorld(TumbleManager.getGameWorld()).getSpawnLocation()) < 402) { + // then remove that block. + event.getHitBlock().setType(Material.AIR); } } } + // Weird stacktrace thing else if (event.getHitBlock().getWorld() == null) { event.setCancelled(true); } @@ -151,12 +163,13 @@ public class EventListener implements Listener{ @EventHandler public void PlayerDropItemEvent(PlayerDropItemEvent event) { - // When an item is dropped, make sure there is a defined gameWorld - if (TumbleManager.getGameWorld() != null) { - // Then check if the item was dropped in the game world - if (event.getPlayer().getWorld() == Bukkit.getWorld((TumbleManager.getGameWorld()))) { - event.setCancelled(true); - } + 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); } } @@ -164,23 +177,21 @@ public class EventListener implements Listener{ public void PlayerMoveEvent(PlayerMoveEvent event) { // 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) + // Cancel the event if the game is starting (so players can't move before the + // game starts) event.setCancelled(true); } } @EventHandler public void FoodLevelChangeEvent(FoodLevelChangeEvent event) { - // When someone's food level changes, check if the gameWorld is null, - if (TumbleManager.getGameWorld() != null) { - // then check if that happened in the gameWorld - if (event.getEntity().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) { - event.setCancelled(true); - } + if (TumbleManager.getGameWorld() == null) { + return; + } + // When someone's food level changes + // check if that happened in the gameWorld + if (event.getEntity().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) { + event.setCancelled(true); } } } - - - - -- cgit v1.2.3 From 3e63a58dba76ab0720711f6c5c602848f606d903 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Fri, 9 Dec 2022 17:00:43 +0000 Subject: remove snowball knockback in game --- README.md | 2 +- .../java/com/MylesAndMore/tumble/EventListener.java | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 04a4a38..e3135c0 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele - [ ] set some limits on the spectator mode in-game; make it so they can't fly outside of the map - [ ] make it so rounds end in a draw after 5m - [ ] make it so that players get snowballs instead of shovels in shovels rounds after 2m 30s -- [ ] remove snowball knockback +- [x] remove snowball knockback ## game logic diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index a5169c5..dd42ea2 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -14,6 +14,7 @@ import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.event.entity.ProjectileLaunchEvent; import org.bukkit.event.player.*; import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; public class EventListener implements Listener { @EventHandler @@ -145,12 +146,23 @@ public class EventListener implements Listener { // 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 player) { - // then check if that block is within the game area, - if (event.getHitBlock().getLocation().distanceSquared( - Bukkit.getWorld(TumbleManager.getGameWorld()).getSpawnLocation()) < 402) { + 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()) < 402) { // 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()); + }, 1); + } } } } -- cgit v1.2.3 From 074bd245939ae6cd29d5e2a55840fdecc512716e Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Fri, 9 Dec 2022 17:33:51 +0000 Subject: start on the clump generation --- .../com/MylesAndMore/tumble/api/Generator.java | 47 +++++++++++++++++++++- .../MylesAndMore/tumble/commands/SetAutoStart.java | 1 - 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/api/Generator.java b/src/main/java/com/MylesAndMore/tumble/api/Generator.java index 1be071d..533ee97 100644 --- a/src/main/java/com/MylesAndMore/tumble/api/Generator.java +++ b/src/main/java/com/MylesAndMore/tumble/api/Generator.java @@ -3,13 +3,30 @@ 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.util.BlockVector; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; 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 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 blocks = new ArrayList<>(); int rSq = radius * radius; @@ -18,12 +35,40 @@ public class Generator { for (int z = Cz - radius; z <= Cz + radius; z++) { if ((Cx - x) * (Cx - x) + (Cz - z) * (Cz - z) <= rSq) { world.getBlockAt(x, y, z).setType(material); + blocks.add(world.getBlockAt(x, y, z)); } } } } + return blocks; + } + + /** + * Generates clumps in a pre-generated layer. + * @param blocks A list of block Locations that this method is allowed to edit + * @param materials 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 blocks, List materials) { + // Define random class + Random random = new Random(); + // This for loop will run until there are no blocks left to change + for (Block aBlock : blocks) { + // Get a random Material from the provided materials list + Material randomMaterial = materials.get(random.nextInt(materials.size())); + aBlock.setType(randomMaterial); + // Get the blocks around that and change it to that same material + // ... + } } + /** + * 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 void generateCuboid(Location firstPos, Location secondPos, Material material) { World world = firstPos.getWorld(); int fX = firstPos.getBlockX(); diff --git a/src/main/java/com/MylesAndMore/tumble/commands/SetAutoStart.java b/src/main/java/com/MylesAndMore/tumble/commands/SetAutoStart.java index 0dcb4d9..4b97d9a 100644 --- a/src/main/java/com/MylesAndMore/tumble/commands/SetAutoStart.java +++ b/src/main/java/com/MylesAndMore/tumble/commands/SetAutoStart.java @@ -1,7 +1,6 @@ package com.MylesAndMore.tumble.commands; import com.MylesAndMore.tumble.TumbleManager; -import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; -- cgit v1.2.3 From a56513d85180c699b566783d7e1ce1f12d641aa4 Mon Sep 17 00:00:00 2001 From: Myles Date: Sat, 10 Dec 2022 01:23:40 -0600 Subject: 1AM COMMIT LETS GOOOO - fixed about 20 bugs, glitches, exploits, you name it--Jacob can break anything (not even joking, did my first *real* playtest; it was...valuable...we'll leave it at that) - added some sort of block balancing (want to improve on it later maybe?) - change the prefix back to lowercase because we're emo or something (COMMONALITY SHUT UP) - game env is now more controlled (thanks Jacob) - can I go to bed now --- README.md | 2 +- .../com/MylesAndMore/tumble/EventListener.java | 120 +++++++++++++++++---- src/main/java/com/MylesAndMore/tumble/Game.java | 40 ++++++- src/main/java/com/MylesAndMore/tumble/Main.java | 10 +- .../tumble/commands/SetWorldConfig.java | 1 + src/main/resources/config.yml | 2 +- 6 files changed, 142 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index e3135c0..e0d0663 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele - [x] make the shovel in shovels mode not lose any durabilty - [x] make it so that you can't move until the game begins -- [ ] make the game blocks breakable very fast, but **not instantly--very important for balancing!!** +- [x] make the game blocks breakable very fast, but **not instantly--very important for balancing!!** - Basically, just set a "cooldown" on both snowballs and shovels--not a long one--but one at that - [ ] add infinite snowballs in the gamemanager for tumble mode - [x] make it so that you can't remove any of the game items from your inventory diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index dd42ea2..a18a9d3 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -4,14 +4,15 @@ import java.util.Objects; import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.entity.Snowball; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.entity.FoodLevelChangeEvent; -import org.bukkit.event.entity.PlayerDeathEvent; -import org.bukkit.event.entity.ProjectileHitEvent; -import org.bukkit.event.entity.ProjectileLaunchEvent; +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; @@ -105,20 +106,18 @@ public class EventListener implements Listener { } @EventHandler - public void ItemDamageEvent(PlayerItemDamageEvent event) { + public void PlayerItemDamageEvent(PlayerItemDamageEvent event) { if (TumbleManager.getGameWorld() == null) { return; } - // On a BlockBreakEvent, - // check to see if the block was broken in the gameWorld, + // On an ItemDamageEvent + // check to see if the item was damaged in the gameWorld, if (event.getPlayer().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) { - // If it was in the gameWorld, check if the roundType was shovels - if (Objects.equals(Game.getGame().getRoundType(), "shovels")) { - event.setCancelled(true); - } + event.setCancelled(true); } } + private long lastTimeP; @EventHandler public void ProjectileLaunchEvent(ProjectileLaunchEvent event) { if (TumbleManager.getGameWorld() == null) { @@ -129,7 +128,22 @@ public class EventListener implements Listener { if (event.getEntity().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) { if (event.getEntity() instanceof Snowball) { if (event.getEntity().getShooter() instanceof Player player) { - player.getInventory().addItem(new ItemStack(Material.SNOWBALL, 1)); + // 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)); + }); + } + } } } } @@ -140,6 +154,10 @@ public class EventListener implements Listener { 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())) { @@ -151,8 +169,8 @@ public class EventListener implements Listener { 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()) < 402) { - // then remove that block. - event.getHitBlock().setType(Material.AIR); + // then remove that block. + event.getHitBlock().setType(Material.AIR); } } else if (event.getHitEntity() != null) { @@ -161,15 +179,11 @@ public class EventListener implements Listener { // then cancel the knockback (has to be delayed by a tick for some reason) Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { hitPlayer.setVelocity(new Vector()); - }, 1); + }); } } } } - // Weird stacktrace thing - else if (event.getHitBlock().getWorld() == null) { - event.setCancelled(true); - } } } @@ -187,10 +201,58 @@ public class EventListener implements Listener { @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) + // 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 if it was with an item enchanted w/ silk touch + if (event.getPlayer().getInventory().getItemInMainHand().containsEnchantment(Enchantment.SILK_TOUCH)) { + // 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); } } @@ -200,10 +262,22 @@ public class EventListener implements Listener { if (TumbleManager.getGameWorld() == null) { return; } - // When someone's food level changes - // check if that happened in the gameWorld + // 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 in the gameWorld, if so, cancel it + if (event.getEntity().getWorld() == Bukkit.getWorld(TumbleManager.getGameWorld())) { + if (event.getEntity() instanceof Player) { + event.setCancelled(true); + } + } + } } diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 6d085df..7de988a 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -6,6 +6,7 @@ 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.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; @@ -78,6 +79,8 @@ public class Game { gameState = "starting"; // Set the roundType to gameType since it won't change for this mode roundType = 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)) { @@ -92,6 +95,7 @@ public class Game { else if (Objects.equals(type, "snowballs")) { gameState = "starting"; roundType = type; + clearInventories(TumbleManager.getPlayersInLobby()); if (generateLayers(type)) { scatterPlayers(TumbleManager.getPlayersInLobby()); } @@ -102,6 +106,7 @@ public class Game { else if (Objects.equals(type, "mixed")) { gameState = "starting"; roundType = type; + clearInventories(TumbleManager.getPlayersInLobby()); if (generateLayers(type)) { scatterPlayers(TumbleManager.getPlayersInLobby()); } @@ -187,7 +192,7 @@ public class Game { // Otherwise, the game must have two people left (and one just died), meaning it is over // This logic is so that it will not remove the last player standing from the list, so we know who the winner is. else { - // roundPlayers.remove(player); + roundPlayers.remove(player); // End the game, passing the winner to the gameEnd method roundEnd(roundPlayers.get(0)); } @@ -229,11 +234,19 @@ public class Game { Generator.generateLayer(layer, 13, 1, Material.AIR); layer.setY(layer.getY() - 1); Generator.generateLayer(layer, 13, 1, Material.GRASS_BLOCK); + Generator.generateLayer(layer, 4, 1, Material.AIR); layer.setY(layer.getY() - 1); Generator.generateLayer(layer, 4, 1, Material.PODZOL); layer.setY(layer.getY() + 2); Generator.generateLayer(layer, 4, 2, Material.TALL_GRASS); - giveItems(TumbleManager.getPlayersInLobby(), new ItemStack(Material.IRON_SHOVEL)); + 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); + } } else if (Objects.equals(type, "snowballs")) { layer.setY(layer.getY() - 1); @@ -244,7 +257,12 @@ public class Game { Generator.generateLayer(layer, 4, 1, Material.AIR); layer.setY(layer.getY() - 1); Generator.generateLayer(layer, 4, 1, Material.LIME_GLAZED_TERRACOTTA); - giveItems(TumbleManager.getPlayersInLobby(), new ItemStack(Material.SNOWBALL)); + 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)); + } } else if (Objects.equals(type, "mixed")) { // Randomly select either shovels or snowballs and re-run the method @@ -273,6 +291,16 @@ public class Game { } } + /** + * Clears the inventories of a provided player list + * @param players The player list for which to clear the inventories of + */ + private void clearInventories(List 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 @@ -370,6 +398,10 @@ public class Game { } // 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); // Re-generate layers generateLayers(roundType); @@ -399,6 +431,8 @@ public class Game { } 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..."); diff --git a/src/main/java/com/MylesAndMore/tumble/Main.java b/src/main/java/com/MylesAndMore/tumble/Main.java index a35a519..16f32c4 100644 --- a/src/main/java/com/MylesAndMore/tumble/Main.java +++ b/src/main/java/com/MylesAndMore/tumble/Main.java @@ -25,15 +25,15 @@ public class Main extends JavaPlugin{ // Check if worlds are null in config if (TumbleManager.getGameWorld() == null) { - Bukkit.getServer().getLogger().warning("[Tumble] It appears you have not configured a game world for Tumble."); - Bukkit.getServer().getLogger().info("[Tumble] If this is your first time running the plugin, you may disregard this message."); + Bukkit.getServer().getLogger().warning("[tumble] It appears you have not configured a game world for Tumble."); + Bukkit.getServer().getLogger().info("[tumble] If this is your first time running the plugin, you may disregard this message."); } if (TumbleManager.getLobbyWorld() == null) { - Bukkit.getServer().getLogger().warning("[Tumble] It appears you have not configured a lobby world for Tumble."); - Bukkit.getServer().getLogger().info("[Tumble] If this is your first time running the plugin, you may disregard this message."); + 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 initialization complete!"); + Bukkit.getServer().getLogger().info("[tumble] Tumble initialization complete!"); } } \ No newline at end of file diff --git a/src/main/java/com/MylesAndMore/tumble/commands/SetWorldConfig.java b/src/main/java/com/MylesAndMore/tumble/commands/SetWorldConfig.java index 74eaf0d..695c248 100644 --- a/src/main/java/com/MylesAndMore/tumble/commands/SetWorldConfig.java +++ b/src/main/java/com/MylesAndMore/tumble/commands/SetWorldConfig.java @@ -52,6 +52,7 @@ public class SetWorldConfig implements CommandExecutor { 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/resources/config.yml b/src/main/resources/config.yml index 6a9f62d..bc68c35 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,5 +1,5 @@ # Hides join/leave messages in public chat -# Default is true +# Default is false hideJoinLeaveMessages: false # Customize the message that displays when the player does not have permission to execute a command from this plugin -- cgit v1.2.3 From 4a7f94c75deb2e9f2a3f4cbab3a7d605626a6d16 Mon Sep 17 00:00:00 2001 From: Myles Date: Sat, 10 Dec 2022 13:32:25 -0600 Subject: this is what you get for not testing things (fix a bug, it might have been game-breaking ._.) --- src/main/java/com/MylesAndMore/tumble/EventListener.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index a18a9d3..8e07509 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -273,10 +273,12 @@ public class EventListener implements Listener { if (TumbleManager.getGameWorld() == null) { return; } - // Check to see if a player got damaged in the gameWorld, if so, cancel it + // 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) { - event.setCancelled(true); + if (event.getCause() == EntityDamageEvent.DamageCause.ENTITY_ATTACK || event.getCause() == EntityDamageEvent.DamageCause.ENTITY_SWEEP_ATTACK) { + event.setCancelled(true); + } } } } -- cgit v1.2.3 From 735fd623a2cb14223df65b17705c4eb6e01a681a Mon Sep 17 00:00:00 2001 From: Myles Date: Sat, 10 Dec 2022 14:49:09 -0600 Subject: lang changes --- src/main/java/com/MylesAndMore/tumble/Main.java | 2 +- src/main/java/com/MylesAndMore/tumble/commands/StartGame.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Main.java b/src/main/java/com/MylesAndMore/tumble/Main.java index 16f32c4..620322c 100644 --- a/src/main/java/com/MylesAndMore/tumble/Main.java +++ b/src/main/java/com/MylesAndMore/tumble/Main.java @@ -34,6 +34,6 @@ public class Main extends JavaPlugin{ } // Init message - Bukkit.getServer().getLogger().info("[tumble] Tumble initialization complete!"); + Bukkit.getServer().getLogger().info("[tumble] tumble successfully enabled!"); } } \ No newline at end of file diff --git a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java index d488fec..652b222 100644 --- a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java +++ b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java @@ -22,7 +22,7 @@ public class StartGame implements CommandExecutor { if (TumbleManager.getGameWorld() != null) { // Check if a game is already pending to start if (!Objects.equals(Game.getGame().getGameState(), "waiting")) { - sender.sendMessage(ChatColor.BLUE + "Starting game, please wait."); + 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())) { -- cgit v1.2.3 From cf6bdc376b91e3c1ab5403e018470a7fee589986 Mon Sep 17 00:00:00 2001 From: Myles Date: Sat, 10 Dec 2022 14:59:58 -0600 Subject: THE CLUMPS WORK --- README.md | 7 +- .../com/MylesAndMore/tumble/EventListener.java | 4 +- src/main/java/com/MylesAndMore/tumble/Game.java | 70 ++++++++-------- .../com/MylesAndMore/tumble/api/Generator.java | 40 +++++++-- .../java/com/MylesAndMore/tumble/api/Layers.java | 95 ++++++++++++++++++++++ 5 files changed, 169 insertions(+), 47 deletions(-) create mode 100644 src/main/java/com/MylesAndMore/tumble/api/Layers.java diff --git a/README.md b/README.md index e0d0663..a560e7c 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,9 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele ## generation -- [ ] layers should be able to generate w/ "clumps" of blocks; instead of only one material as a whole - - [ ] the clump size should be customizable (for later); be able to set a min/max val and it will choose randomly per each clump (not in config file yet, just internally) +- [x] layers should be able to generate w/ "clumps" of blocks; instead of only one material as a whole + - [x] the clump size should be customizable (for later); be able to set a min/max val and it will choose randomly per each clump (not in config file yet, just internally) + - *Note: this is done through the amount of times each Material shows up in the List--there's no config for it.* - [ ] make shovels generation actually work properly - make different types of platforms (square, circle, multi-tiered, etc.); still should be pseudo-random - [ ] make snowballs generation actually work properly (shocker) @@ -18,7 +19,7 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele - [x] make it so that you can't move until the game begins - [x] make the game blocks breakable very fast, but **not instantly--very important for balancing!!** - Basically, just set a "cooldown" on both snowballs and shovels--not a long one--but one at that -- [ ] add infinite snowballs in the gamemanager for tumble mode +- [x] add infinite snowballs in the gamemanager for tumble mode - [x] make it so that you can't remove any of the game items from your inventory - [x] make snowballs actually break blocks (duh) - [x] make the randomized mode logic diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index 8e07509..7e7bf94 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -128,8 +128,8 @@ public class EventListener implements Listener { 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); } + // Check to see if the last snowball was thrown less than 210ms ago, if so, don't allow another + if ((System.currentTimeMillis() - lastTimeP) < 205) { event.setCancelled(true); } else { // Otherwise, continue with logic lastTimeP = System.currentTimeMillis(); diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 7de988a..789edff 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -2,6 +2,7 @@ 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; @@ -37,8 +38,8 @@ public class Game { // 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 roundType - private String roundType; + // Define a variable for the gameType + private String gameType; // Define a variable for the autostart PID private int autoStartID = -1; @@ -77,8 +78,8 @@ public class Game { // Define the gameType if (Objects.equals(type, "shovels")) { gameState = "starting"; - // Set the roundType to gameType since it won't change for this mode - roundType = type; + // 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 @@ -94,7 +95,7 @@ public class Game { } else if (Objects.equals(type, "snowballs")) { gameState = "starting"; - roundType = type; + gameType = type; clearInventories(TumbleManager.getPlayersInLobby()); if (generateLayers(type)) { scatterPlayers(TumbleManager.getPlayersInLobby()); @@ -105,7 +106,7 @@ public class Game { } else if (Objects.equals(type, "mixed")) { gameState = "starting"; - roundType = type; + gameType = type; clearInventories(TumbleManager.getPlayersInLobby()); if (generateLayers(type)) { scatterPlayers(TumbleManager.getPlayersInLobby()); @@ -184,6 +185,7 @@ public class Game { */ public void playerDeath(Player player) { player.setGameMode(GameMode.SPECTATOR); + player.teleport(gameSpawn); // If there are more than 2 players in the game, if (roundPlayers.size() > 2) { // remove that player (who just died) from the roundPlayersArray, effectively eliminating them, @@ -200,11 +202,6 @@ public class Game { // Methods to get the game type and game state for other classes outside the Game - /** - * @return The round type of the current round as a String ("shovels", "snowballs") - */ - public String getRoundType() { return roundType; } - /** * @return The game's current state as a String ("waiting", "starting", "running", "complete") * Can also be null if not initialized. @@ -225,20 +222,20 @@ public class Game { * @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 */ + // Initialize Layers + private final Layers layers = new Layers(); 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); - Generator.generateLayer(layer, 17, 1, Material.SNOW_BLOCK); + 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.generateLayer(layer, 13, 1, Material.GRASS_BLOCK); + 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.generateLayer(layer, 4, 1, Material.PODZOL); - layer.setY(layer.getY() + 2); - Generator.generateLayer(layer, 4, 2, Material.TALL_GRASS); + Generator.generateClumps(Generator.generateLayer(layer, 4, 1, Material.PODZOL), layers.getMaterialList()); ItemStack shovel = new ItemStack(Material.IRON_SHOVEL); shovel.addEnchantment(Enchantment.SILK_TOUCH, 1); if (Objects.equals(gameState, "running")) { @@ -250,13 +247,13 @@ public class Game { } else if (Objects.equals(type, "snowballs")) { layer.setY(layer.getY() - 1); - Generator.generateLayer(layer, 17, 1, Material.COAL_ORE); + Generator.generateClumps(Generator.generateLayer(layer, 17, 1, Material.STONE), layers.getMaterialList()); Generator.generateLayer(layer, 13, 1, Material.AIR); layer.setY(layer.getY() - 1); - Generator.generateLayer(layer, 13, 1, Material.GRANITE); + Generator.generateClumps(Generator.generateLayer(layer, 13, 1, Material.GRANITE), layers.getMaterialList()); Generator.generateLayer(layer, 4, 1, Material.AIR); layer.setY(layer.getY() - 1); - Generator.generateLayer(layer, 4, 1, Material.LIME_GLAZED_TERRACOTTA); + Generator.generateClumps(Generator.generateLayer(layer, 4, 1, Material.LIME_GLAZED_TERRACOTTA), layers.getMaterialList()); if (Objects.equals(gameState, "running")) { giveItems(TumbleManager.getPlayersInGame(), new ItemStack(Material.SNOWBALL)); } @@ -403,30 +400,33 @@ public class Game { roundPlayers.addAll(gamePlayers); clearInventories(gamePlayers); displayTitles(gamePlayers, ChatColor.RED + "Round over!", ChatColor.GOLD + winner.getName() + " has won the round!", 5, 60, 5); - // Re-generate layers - generateLayers(roundType); - // Wait 5s (100t) for tp method + // Wait for player to respawn before completely l a g g i n g the server ._. Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { - // Re-scatter players - gameState = "starting"; - scatterPlayers(gamePlayers); - playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 1, 1); - displayTitles(gamePlayers, ChatColor.DARK_GREEN + "3", null, 3, 10, 7); + // Re-generate layers + generateLayers(gameType); + // Wait 5s (100t) for tp method Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { + // Re-scatter players + gameState = "starting"; + scatterPlayers(gamePlayers); playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 1, 1); - displayTitles(gamePlayers, ChatColor.YELLOW + "2", null, 3, 10, 7); + 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, 1, 1); - displayTitles(gamePlayers, ChatColor.DARK_RED + "1", null, 3, 10, 7); + displayTitles(gamePlayers, ChatColor.YELLOW + "2", null, 3, 10, 7); Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { - playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 1, 2); - displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1); - setGamemode(gamePlayers, GameMode.SURVIVAL); - gameState = "running"; + playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 1, 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, 1, 2); + displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1); + setGamemode(gamePlayers, GameMode.SURVIVAL); + gameState = "running"; + }, 20); }, 20); }, 20); - }, 20); - }, 100); + }, 100); + }, 1); } } diff --git a/src/main/java/com/MylesAndMore/tumble/api/Generator.java b/src/main/java/com/MylesAndMore/tumble/api/Generator.java index 533ee97..f4439b6 100644 --- a/src/main/java/com/MylesAndMore/tumble/api/Generator.java +++ b/src/main/java/com/MylesAndMore/tumble/api/Generator.java @@ -1,12 +1,14 @@ package com.MylesAndMore.tumble.api; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Block; -import org.bukkit.util.BlockVector; +import org.bukkit.block.BlockFace; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Random; @@ -45,21 +47,45 @@ public class Generator { /** * Generates clumps in a pre-generated layer. - * @param blocks A list of block Locations that this method is allowed to edit - * @param materials A list of Materials for the generator to randomly choose from. + * @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 blocks, List materials) { + public static void generateClumps(List blockList, List materialList) { // Define random class Random random = new Random(); - // This for loop will run until there are no blocks left to change - for (Block aBlock : blocks) { + // Define new blocks list so we can manipulate it + List blocks = new ArrayList<>(blockList); + // Define new shuffled Materials list + List 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..b970891 --- /dev/null +++ b/src/main/java/com/MylesAndMore/tumble/api/Layers.java @@ -0,0 +1,95 @@ +package com.MylesAndMore.tumble.api; + +import org.bukkit.Material; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +/** + * This class is dedicated to storing the different types of layers that can be generated. + */ +public class Layers { + + public Layers(){ + matList.add(gen0); + matList.add(gen0); + matList.add(gen0); + matList.add(gen1); + matList.add(gen1); + matList.add(gen0); + matList.add(gen0); + matList.add(gen0); + matList.add(gen1); + matList.add(gen1); + matList.add(gen2); + } + + // 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 getMaterialList() { + return matList.get(random.nextInt(matList.size())); + } + + + // Begin lists + + // private final List gen = new ArrayList<>() {{ + // add(Material.); + // }}; + + private final List 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.COBWEB); + add(Material.GRASS_BLOCK); + add(Material.GRASS_BLOCK); + }}; + + private final List 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 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); + }}; + + private final List> matList = new ArrayList<>(); + +} -- cgit v1.2.3 From 6aab3dfcbb7636e1b11cd54e10bddff45f5ef8e9 Mon Sep 17 00:00:00 2001 From: Myles Date: Sat, 10 Dec 2022 17:53:00 -0600 Subject: musik --- README.md | 3 +- .../com/MylesAndMore/tumble/EventListener.java | 4 +- src/main/java/com/MylesAndMore/tumble/Game.java | 47 +++++++++++++++------- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index a560e7c..222d423 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,6 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele - [x] make it so that you can't remove any of the game items from your inventory - [x] make snowballs actually break blocks (duh) - [x] make the randomized mode logic -- [ ] set some limits on the spectator mode in-game; make it so they can't fly outside of the map - [ ] make it so rounds end in a draw after 5m - [ ] make it so that players get snowballs instead of shovels in shovels rounds after 2m 30s - [x] remove snowball knockback @@ -48,4 +47,4 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele - [x] refactor EventListener null checker code - if (TumbleManager.getGameWorld() == null && TumbleManager.getLobbyWorld() == null) { return; } -- [ ] add game music? but probably only for us; I feel like the og music must be copyrighted +- [x] add game music? but probably only for us; I feel like the og music must be copyrighted diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index 7e7bf94..8e07509 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -128,8 +128,8 @@ public class EventListener implements Listener { 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 210ms ago, if so, don't allow another - if ((System.currentTimeMillis() - lastTimeP) < 205) { event.setCancelled(true); } + // 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(); diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 789edff..b5932e3 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -130,19 +130,20 @@ public class Game { // 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, 1, 1); + 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, 1, 1); + 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, 1, 1); + 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, 1, 2); + 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"; + playMusic(gamePlayers, SoundCategory.NEUTRAL, 1, 1); }, 20); }, 20); }, 20); @@ -351,6 +352,26 @@ public class Game { } } + private void playMusic(@NotNull List players, @NotNull SoundCategory category, float volume, float pitch) { + List sounds = new ArrayList<>(List.of( + "minecraft:tumble.0", + "minecraft:tumble.1", + "minecraft:tumble.2", + "minecraft:tumble.3", + "minecraft:tumble.4", + "minecraft:tumble.5", + "minecraft:tumble.6", + "minecraft:tumble.7", + "minecraft:tumble.8", + "minecraft:tumble.9")); + for (Player aPlayer : players) { + aPlayer.playSound(aPlayer.getLocation(), sounds.get(Random.nextInt(sounds.size())), category, volume, pitch); + } + Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { + playMusic(gamePlayers, SoundCategory.NEUTRAL, 1, 1); + }, 1460); + } + /** * Teleports a list of players to the specified scatter locations in the gameWorld * @param players a List of Players to teleport @@ -361,17 +382,15 @@ public class Game { double y = gameSpawn.getY(); double z = gameSpawn.getZ(); // Create the scatter locations based off the game's spawn - List scatterLocations = new ArrayList<>(); - scatterLocations.addAll(List.of( - new Location(gameWorld, (x - 14.5), y, (z + 0.5) , -90, 0), + List 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 + 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)) - ); + 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 @@ -409,16 +428,16 @@ public class Game { // Re-scatter players gameState = "starting"; scatterPlayers(gamePlayers); - playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 1, 1); + 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, 1, 1); + 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, 1, 1); + 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, 1, 2); + 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"; -- cgit v1.2.3 From 9b6ef346a5bd3de1a54600bd4aece287a7cbb526 Mon Sep 17 00:00:00 2001 From: Myles Date: Sun, 11 Dec 2022 01:07:30 -0600 Subject: remove snowball limiter because it was too problematic --- src/main/java/com/MylesAndMore/tumble/EventListener.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index 8e07509..0de9a86 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -117,7 +117,7 @@ public class EventListener implements Listener { } } - private long lastTimeP; + // private long lastTimeP; @EventHandler public void ProjectileLaunchEvent(ProjectileLaunchEvent event) { if (TumbleManager.getGameWorld() == null) { @@ -129,11 +129,11 @@ public class EventListener implements Listener { 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 ((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); } @@ -143,7 +143,7 @@ public class EventListener implements Listener { player.getInventory().addItem(new ItemStack(Material.SNOWBALL, 1)); }); } - } + // } } } } -- cgit v1.2.3 From bfc632c3d5d9b4419de023542c32a58869c7eb60 Mon Sep 17 00:00:00 2001 From: Myles Date: Sun, 11 Dec 2022 01:08:11 -0600 Subject: fix bugs --- src/main/java/com/MylesAndMore/tumble/Game.java | 26 +++++++++++++++++++--- .../MylesAndMore/tumble/commands/StartGame.java | 2 +- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index b5932e3..064b5ae 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -8,6 +8,8 @@ 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; @@ -42,6 +44,8 @@ public class Game { private String gameType; // Define a variable for the autostart PID private int autoStartID = -1; + // Define a variable for music ID + private int musicID = -1; // Initialize a new instance of the Random class for use later private final Random Random = new Random(); @@ -186,7 +190,14 @@ public class Game { */ public void playerDeath(Player player) { player.setGameMode(GameMode.SPECTATOR); - player.teleport(gameSpawn); + // 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); // If there are more than 2 players in the game, if (roundPlayers.size() > 2) { // remove that player (who just died) from the roundPlayersArray, effectively eliminating them, @@ -364,10 +375,11 @@ public class Game { "minecraft:tumble.7", "minecraft:tumble.8", "minecraft:tumble.9")); + String currentSong = sounds.get(Random.nextInt(sounds.size())); for (Player aPlayer : players) { - aPlayer.playSound(aPlayer.getLocation(), sounds.get(Random.nextInt(sounds.size())), category, volume, pitch); + aPlayer.playSound(aPlayer.getLocation(), currentSong, category, volume, pitch); } - Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { + musicID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { playMusic(gamePlayers, SoundCategory.NEUTRAL, 1, 1); }, 1460); } @@ -425,6 +437,12 @@ public class Game { 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); @@ -457,6 +475,8 @@ public class Game { displayActionbar(gamePlayers, ChatColor.BLUE + "Returning to lobby in ten seconds..."); // Wait 10s (200t), then Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { + // Stop music from replaying + Bukkit.getServer().getScheduler().cancelTask(musicID); // 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 diff --git a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java index 652b222..c138cda 100644 --- a/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java +++ b/src/main/java/com/MylesAndMore/tumble/commands/StartGame.java @@ -17,7 +17,7 @@ public class StartGame implements CommandExecutor { // Check if there is a lobbyWorld specified in config if (TumbleManager.getLobbyWorld() != null) { // Check if there is more than one person in lobby - if (TumbleManager.getPlayersInLobby().size() > 0) { + if (TumbleManager.getPlayersInLobby().size() > 1) { // Check if there is a gameWorld specified in config if (TumbleManager.getGameWorld() != null) { // Check if a game is already pending to start -- cgit v1.2.3 From aedd6cdd4013061010e6c2c2fb1a88e085d2470b Mon Sep 17 00:00:00 2001 From: Myles Date: Sun, 11 Dec 2022 01:08:22 -0600 Subject: add new layer types --- .../java/com/MylesAndMore/tumble/api/Layers.java | 196 +++++++++++++++++++-- 1 file changed, 186 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/api/Layers.java b/src/main/java/com/MylesAndMore/tumble/api/Layers.java index b970891..fba6fbf 100644 --- a/src/main/java/com/MylesAndMore/tumble/api/Layers.java +++ b/src/main/java/com/MylesAndMore/tumble/api/Layers.java @@ -13,16 +13,17 @@ public class Layers { public Layers(){ matList.add(gen0); - matList.add(gen0); - matList.add(gen0); - matList.add(gen1); - matList.add(gen1); - matList.add(gen0); - matList.add(gen0); - matList.add(gen0); - matList.add(gen1); 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(gen11); } // Define Random class @@ -38,7 +39,7 @@ public class Layers { // Begin lists // private final List gen = new ArrayList<>() {{ - // add(Material.); + // add(Material. // }}; private final List gen0 = new ArrayList<>() {{ @@ -53,9 +54,11 @@ public class Layers { add(Material.GOLD_ORE); add(Material.LAPIS_ORE); add(Material.DIAMOND_ORE); - add(Material.COBWEB); add(Material.GRASS_BLOCK); add(Material.GRASS_BLOCK); + add(Material.GRASS_BLOCK); + add(Material.GRASS_BLOCK); + // add(Material.COBWEB); }}; private final List gen1 = new ArrayList<>() {{ @@ -88,6 +91,179 @@ public class Layers { add(Material.GREEN_TERRACOTTA); add(Material.YELLOW_TERRACOTTA); add(Material.WHITE_STAINED_GLASS); + add(Material.HONEYCOMB_BLOCK); + add(Material.HONEYCOMB_BLOCK); + }}; + + private final List gen3 = new ArrayList<>() {{ + add(Material.PACKED_ICE); + add(Material.ICE); + add(Material.PACKED_ICE); + add(Material.ICE); + add(Material.NOTE_BLOCK); + add(Material.TNT); + add(Material.LIGHT_BLUE_CONCRETE); + add(Material.GLASS); + add(Material.PACKED_ICE); + add(Material.ICE); + add(Material.PACKED_ICE); + add(Material.ICE); + add(Material.NOTE_BLOCK); + add(Material.TNT); + add(Material.LIGHT_BLUE_CONCRETE); + add(Material.GLASS); + add(Material.SOUL_SAND); + }}; + + private final List 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 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 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); + }}; + + private final List 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 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 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 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 gen11 = new ArrayList<>() {{ + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.GLASS); + add(Material.WHITE_STAINED_GLASS); }}; private final List> matList = new ArrayList<>(); -- cgit v1.2.3 From b3a697e36b2f86ac215ee766c2b6f7ddf123e0fb Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Sun, 11 Dec 2022 17:49:35 +0000 Subject: make rounds timed --- README.md | 4 +- src/main/java/com/MylesAndMore/tumble/Game.java | 68 +++++++++++++++++----- src/main/java/com/MylesAndMore/tumble/Main.java | 2 +- .../com/MylesAndMore/tumble/api/Generator.java | 1 - 4 files changed, 55 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 222d423..8add728 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele - [x] make it so that you can't remove any of the game items from your inventory - [x] make snowballs actually break blocks (duh) - [x] make the randomized mode logic -- [ ] make it so rounds end in a draw after 5m -- [ ] make it so that players get snowballs instead of shovels in shovels rounds after 2m 30s +- [x] make it so rounds end in a draw after 5m +- [x] make it so that players get snowballs instead of shovels in shovels rounds after 2m 30s - [x] remove snowball knockback ## game logic diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 064b5ae..2b3d7b4 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -42,6 +42,8 @@ public class Game { 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 for music ID @@ -91,7 +93,6 @@ public class Game { if (generateLayers(type)) { // Send all players from lobby to the game scatterPlayers(TumbleManager.getPlayersInLobby()); - // Keep in mind that after this runs, this command will complete and return true } else { return false; @@ -256,6 +257,17 @@ public class Game { 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!"); + // 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); @@ -272,6 +284,10 @@ public class Game { 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 @@ -364,7 +380,9 @@ public class Game { } private void playMusic(@NotNull List players, @NotNull SoundCategory category, float volume, float pitch) { - List sounds = new ArrayList<>(List.of( + List sounds = new ArrayList<>(); + if (sounds.size() == 0) { + sounds = new ArrayList<>(List.of( "minecraft:tumble.0", "minecraft:tumble.1", "minecraft:tumble.2", @@ -375,13 +393,17 @@ public class Game { "minecraft:tumble.7", "minecraft:tumble.8", "minecraft:tumble.9")); - String currentSong = sounds.get(Random.nextInt(sounds.size())); - for (Player aPlayer : players) { - aPlayer.playSound(aPlayer.getLocation(), currentSong, category, volume, pitch); } - musicID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { - playMusic(gamePlayers, SoundCategory.NEUTRAL, 1, 1); - }, 1460); + else { + String currentSong = sounds.get(Random.nextInt(sounds.size())); + for (Player aPlayer : players) { + aPlayer.playSound(aPlayer.getLocation(), currentSong, category, volume, pitch); + } + sounds.remove(currentSong); + musicID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { + playMusic(gamePlayers, SoundCategory.NEUTRAL, 1, 1); + }, 1460); + } } /** @@ -414,15 +436,23 @@ public class Game { } } - private void roundEnd(Player winner) { - // Set the wins of the player to their current # of wins + 1 - gameWins.set(gamePlayers.indexOf(winner), (gameWins.get(gamePlayers.indexOf(winner)) + 1)); + private void roundEnd(@Nullable Player winner) { + // Cancel the tasks to auto-end the round + Bukkit.getServer().getScheduler().cancelTask(gameID); + // Check if there was a winner of the round + 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)); + } // Clear old layers (as a fill command, this would be /fill ~-20 ~-4 ~-20 ~20 ~ ~20 relative to spawn) Generator.generateCuboid(new Location(gameSpawn.getWorld(), gameSpawn.getX() - 20, gameSpawn.getY() - 4, 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); - // If the player has three wins, they won the game, so initiate the gameEnd - if (gameWins.get(gamePlayers.indexOf(winner)) == 3) { - gameEnd(winner); + // Again, check if there was a winner to...win + if (winner != null) { + // 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 { @@ -430,8 +460,14 @@ public class Game { 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 ._. + // Display personalized title if someone won, generalized if not + if (winner != null) { + displayTitles(gamePlayers, ChatColor.RED + "Round over!", ChatColor.GOLD + winner.getName() + " has won the round!", 5, 60, 5); + } + else { + 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); diff --git a/src/main/java/com/MylesAndMore/tumble/Main.java b/src/main/java/com/MylesAndMore/tumble/Main.java index 620322c..73dedf5 100644 --- a/src/main/java/com/MylesAndMore/tumble/Main.java +++ b/src/main/java/com/MylesAndMore/tumble/Main.java @@ -34,6 +34,6 @@ public class Main extends JavaPlugin{ } // Init message - Bukkit.getServer().getLogger().info("[tumble] tumble successfully enabled!"); + Bukkit.getServer().getLogger().info("[tumble] Tumble successfully enabled!"); } } \ No newline at end of file diff --git a/src/main/java/com/MylesAndMore/tumble/api/Generator.java b/src/main/java/com/MylesAndMore/tumble/api/Generator.java index f4439b6..d66352a 100644 --- a/src/main/java/com/MylesAndMore/tumble/api/Generator.java +++ b/src/main/java/com/MylesAndMore/tumble/api/Generator.java @@ -1,6 +1,5 @@ package com.MylesAndMore.tumble.api; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; -- cgit v1.2.3 From 143d998a9d6df2ce69594e90e88cc9e9be8c48a1 Mon Sep 17 00:00:00 2001 From: Myles Date: Sun, 11 Dec 2022 16:32:32 -0600 Subject: add new layer types and gen types --- README.md | 4 +- .../com/MylesAndMore/tumble/EventListener.java | 15 +- src/main/java/com/MylesAndMore/tumble/Game.java | 232 +++++++++++++-------- .../com/MylesAndMore/tumble/api/Generator.java | 51 ++--- .../java/com/MylesAndMore/tumble/api/Layers.java | 80 ++++++- 5 files changed, 260 insertions(+), 122 deletions(-) diff --git a/README.md b/README.md index 8add728..185e2b9 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ once this list is complete and all bugs are fixed, we *should* be ready for rele - [x] layers should be able to generate w/ "clumps" of blocks; instead of only one material as a whole - [x] the clump size should be customizable (for later); be able to set a min/max val and it will choose randomly per each clump (not in config file yet, just internally) - *Note: this is done through the amount of times each Material shows up in the List--there's no config for it.* -- [ ] make shovels generation actually work properly +- [x] make shovels generation actually work properly - make different types of platforms (square, circle, multi-tiered, etc.); still should be pseudo-random -- [ ] make snowballs generation actually work properly (shocker) +- [x] make snowballs generation actually work properly (shocker) - make three layers generate (same layer types as shovels, just multiple of them) ## game realism diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index 0de9a86..03d786e 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -168,7 +168,7 @@ public class EventListener implements Listener { // 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()) < 402) { + if (event.getHitBlock().getLocation().distanceSquared(Bukkit.getWorld(TumbleManager.getGameWorld()).getSpawnLocation()) < 579) { // then remove that block. event.getHitBlock().setType(Material.AIR); } @@ -231,15 +231,12 @@ public class EventListener implements Listener { // 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 if it was with an item enchanted w/ silk touch - if (event.getPlayer().getInventory().getItemInMainHand().containsEnchantment(Enchantment.SILK_TOUCH)) { - // Then check to see if the player interacted less than 150ms ago - if ((System.currentTimeMillis() - lastTimeI) < 150) return; + // 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); - } + else { + lastTimeI = System.currentTimeMillis(); + event.getClickedBlock().setType(Material.AIR); } } } diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 2b3d7b4..3d83d23 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -48,6 +48,8 @@ public class Game { private int autoStartID = -1; // Define a variable for music ID private int musicID = -1; + // Define a variable to keep the list of tracks that have already played in the game + List sounds = new ArrayList<>(); // Initialize a new instance of the Random class for use later private final Random Random = new Random(); @@ -82,47 +84,27 @@ public class Game { } else { // Define the gameType - if (Objects.equals(type, "shovels")) { - 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; - } - } - else if (Objects.equals(type, "snowballs")) { - gameState = "starting"; - gameType = type; - clearInventories(TumbleManager.getPlayersInLobby()); - if (generateLayers(type)) { - scatterPlayers(TumbleManager.getPlayersInLobby()); - } - else { - return false; - } - } - else if (Objects.equals(type, "mixed")) { - gameState = "starting"; - gameType = type; - clearInventories(TumbleManager.getPlayersInLobby()); - if (generateLayers(type)) { - scatterPlayers(TumbleManager.getPlayersInLobby()); - } - else { + 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; - } - } - else { - // 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 @@ -230,25 +212,47 @@ public class Game { // 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 */ - // Initialize Layers - private final Layers layers = new Layers(); 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); - 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()); + // 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")) { @@ -263,6 +267,7 @@ public class Game { 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); @@ -271,13 +276,79 @@ public class Game { } else if (Objects.equals(type, "snowballs")) { layer.setY(layer.getY() - 1); - 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()); + // 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)); } @@ -285,9 +356,7 @@ public class Game { giveItems(TumbleManager.getPlayersInLobby(), new ItemStack(Material.SNOWBALL)); } // End the round in 5m - gameID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { - roundEnd(null); - }, 6160); + 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 @@ -380,30 +449,27 @@ public class Game { } private void playMusic(@NotNull List players, @NotNull SoundCategory category, float volume, float pitch) { - List sounds = new ArrayList<>(); if (sounds.size() == 0) { - sounds = new ArrayList<>(List.of( - "minecraft:tumble.0", - "minecraft:tumble.1", - "minecraft:tumble.2", - "minecraft:tumble.3", - "minecraft:tumble.4", - "minecraft:tumble.5", - "minecraft:tumble.6", - "minecraft:tumble.7", - "minecraft:tumble.8", - "minecraft:tumble.9")); + sounds.addAll(List.of( + "minecraft:tumble.0", + "minecraft:tumble.1", + "minecraft:tumble.2", + "minecraft:tumble.3", + "minecraft:tumble.4", + "minecraft:tumble.5", + "minecraft:tumble.6", + "minecraft:tumble.7", + "minecraft:tumble.8", + "minecraft:tumble.9")); } - else { - String currentSong = sounds.get(Random.nextInt(sounds.size())); - for (Player aPlayer : players) { - aPlayer.playSound(aPlayer.getLocation(), currentSong, category, volume, pitch); - } - sounds.remove(currentSong); - musicID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { - playMusic(gamePlayers, SoundCategory.NEUTRAL, 1, 1); - }, 1460); + String currentSong = sounds.get(Random.nextInt(sounds.size())); + for (Player aPlayer : players) { + aPlayer.playSound(aPlayer.getLocation(), currentSong, category, volume, pitch); } + sounds.remove(currentSong); + musicID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { + playMusic(gamePlayers, SoundCategory.NEUTRAL, 1, 1); + }, 1460); } /** @@ -437,15 +503,15 @@ public class Game { } private void roundEnd(@Nullable Player winner) { - // Cancel the tasks to auto-end the round + // Cancel the tasks that auto-end the round Bukkit.getServer().getScheduler().cancelTask(gameID); // Check if there was a winner of the round 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)); } - // Clear old layers (as a fill command, this would be /fill ~-20 ~-4 ~-20 ~20 ~ ~20 relative to spawn) - Generator.generateCuboid(new Location(gameSpawn.getWorld(), gameSpawn.getX() - 20, gameSpawn.getY() - 4, gameSpawn.getZ() - 20), new Location(gameSpawn.getWorld(), gameSpawn.getX() + 20, gameSpawn.getY(), gameSpawn.getZ() + 20), Material.AIR); + // 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); // Again, check if there was a winner to...win if (winner != null) { diff --git a/src/main/java/com/MylesAndMore/tumble/api/Generator.java b/src/main/java/com/MylesAndMore/tumble/api/Generator.java index d66352a..0a35767 100644 --- a/src/main/java/com/MylesAndMore/tumble/api/Generator.java +++ b/src/main/java/com/MylesAndMore/tumble/api/Generator.java @@ -44,6 +44,33 @@ public class Generator { 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 generateCuboid(Location firstPos, Location secondPos, Material material) { + World world = firstPos.getWorld(); + List 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 @@ -87,28 +114,4 @@ public class Generator { blocks.remove(aBlock); } } - - /** - * 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 void generateCuboid(Location firstPos, Location secondPos, Material material) { - World world = firstPos.getWorld(); - 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); - } - } - } - } } diff --git a/src/main/java/com/MylesAndMore/tumble/api/Layers.java b/src/main/java/com/MylesAndMore/tumble/api/Layers.java index fba6fbf..dad5ea8 100644 --- a/src/main/java/com/MylesAndMore/tumble/api/Layers.java +++ b/src/main/java/com/MylesAndMore/tumble/api/Layers.java @@ -23,6 +23,41 @@ public class Layers { matList.add(gen8); matList.add(gen9); matList.add(gen10); + matList.add(gen12); + matList.add(gen14); + matList.add(gen15); + matList.add(gen16); + matList.add(gen0); + matList.add(gen1); + matList.add(gen2); + matList.add(gen3); + matList.add(gen4); + matList.add(gen5); + matList.add(gen6); + matList.add(gen7); + matList.add(gen8); + matList.add(gen9); + matList.add(gen10); + matList.add(gen12); + matList.add(gen14); + matList.add(gen15); + matList.add(gen16); + matList.add(gen0); + matList.add(gen1); + matList.add(gen2); + matList.add(gen3); + matList.add(gen4); + matList.add(gen5); + matList.add(gen6); + matList.add(gen7); + matList.add(gen8); + matList.add(gen9); + matList.add(gen10); + matList.add(gen12); + matList.add(gen14); + matList.add(gen15); + matList.add(gen16); + // Troll glass layer matList.add(gen11); } @@ -97,17 +132,13 @@ public class Layers { private final List gen3 = new ArrayList<>() {{ add(Material.PACKED_ICE); - add(Material.ICE); add(Material.PACKED_ICE); - add(Material.ICE); add(Material.NOTE_BLOCK); add(Material.TNT); add(Material.LIGHT_BLUE_CONCRETE); add(Material.GLASS); add(Material.PACKED_ICE); - add(Material.ICE); add(Material.PACKED_ICE); - add(Material.ICE); add(Material.NOTE_BLOCK); add(Material.TNT); add(Material.LIGHT_BLUE_CONCRETE); @@ -170,6 +201,7 @@ public class Layers { add(Material.RED_NETHER_BRICKS); add(Material.NETHER_WART_BLOCK); add(Material.CRYING_OBSIDIAN); + add(Material.MAGMA_BLOCK); }}; private final List gen7 = new ArrayList<>() {{ @@ -266,6 +298,46 @@ public class Layers { add(Material.WHITE_STAINED_GLASS); }}; + private final List 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 gen14 = new ArrayList<>() {{ + add(Material.LECTERN); + add(Material.OBSIDIAN); + add(Material.SPONGE); + add(Material.BEEHIVE); + add(Material.DRIED_KELP_BLOCK); + }}; + + private final List 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 gen16 = new ArrayList<>() {{ + add(Material.JUNGLE_LOG); + add(Material.STRIPPED_JUNGLE_LOG); + add(Material.JUNGLE_WOOD); + add(Material.STRIPPED_JUNGLE_WOOD); + add(Material.MOSSY_COBBLESTONE); + add(Material.MOSSY_COBBLESTONE); + add(Material.MOSSY_COBBLESTONE); + add(Material.JUNGLE_LEAVES); + add(Material.JUNGLE_SLAB); + add(Material.JUNGLE_TRAPDOOR); + }}; + private final List> matList = new ArrayList<>(); } -- cgit v1.2.3 From 3a53bbe9f0b29bc5d8130cdc570f7bd40316378a Mon Sep 17 00:00:00 2001 From: Myles Date: Sun, 11 Dec 2022 20:03:18 -0600 Subject: fix (hopefully the last!) bugs --- .../com/MylesAndMore/tumble/EventListener.java | 14 ++-- src/main/java/com/MylesAndMore/tumble/Game.java | 76 +++++++++++++++------- 2 files changed, 58 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index 03d786e..d6b3ffa 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -222,7 +222,7 @@ public class EventListener implements Listener { } } - private long lastTimeI; + // private long lastTimeI; @EventHandler public void PlayerInteractEvent(PlayerInteractEvent event) { if (TumbleManager.getGameWorld() == null) { @@ -232,12 +232,12 @@ public class EventListener implements Listener { 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 ((System.currentTimeMillis() - lastTimeI) < 150) return; // If not, set that block to air (break it) - else { - lastTimeI = System.currentTimeMillis(); - event.getClickedBlock().setType(Material.AIR); - } + // else { + // lastTimeI = System.currentTimeMillis(); + event.getClickedBlock().setType(Material.AIR); + // } } } } @@ -273,7 +273,7 @@ public class EventListener implements Listener { // 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) { + 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 index 3d83d23..58c42a5 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -181,15 +181,10 @@ public class Game { player.setGameMode(GameMode.SPECTATOR); }, 5); }, 5); - // If there are more than 2 players in the game, - if (roundPlayers.size() > 2) { - // remove that player (who just died) from the roundPlayersArray, effectively eliminating them, - roundPlayers.remove(player); - } - // Otherwise, the game must have two people left (and one just died), meaning it is over - // This logic is so that it will not remove the last player standing from the list, so we know who the winner is. - else { - roundPlayers.remove(player); + // 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)); } @@ -505,34 +500,65 @@ public class Game { private void roundEnd(@Nullable Player winner) { // Cancel the tasks that auto-end the round Bukkit.getServer().getScheduler().cancelTask(gameID); - // Check if there was a winner of the round - 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)); - } // 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); - // Again, check if there was a winner to...win + // 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); + } } - // 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); + setGamemode(gamePlayers, GameMode.SPECTATOR); + roundPlayers.removeAll(roundPlayers); roundPlayers.addAll(gamePlayers); clearInventories(gamePlayers); - // Display personalized title if someone won, generalized if not - if (winner != null) { - displayTitles(gamePlayers, ChatColor.RED + "Round over!", ChatColor.GOLD + winner.getName() + " has won the round!", 5, 60, 5); - } - else { - displayTitles(gamePlayers, ChatColor.RED + "Round over!", ChatColor.GOLD + "Draw!", 5, 60, 5); - } + 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 -- cgit v1.2.3 From 23429bbd3fe7e35ab9877e536f9ff9a2e71a9afc Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Mon, 12 Dec 2022 19:21:09 +0000 Subject: refactoring to prep for release!! - refactor a bit of code - add a bit more documentations - remove music code--we can't redistribute the music in a pack :( - remove old readme--writing the new docs tonight or tmrw we got this! --- README.md | 51 +------------ .../com/MylesAndMore/tumble/EventListener.java | 4 +- src/main/java/com/MylesAndMore/tumble/Game.java | 35 +-------- .../com/MylesAndMore/tumble/TumbleManager.java | 3 + .../com/MylesAndMore/tumble/api/Generator.java | 3 + .../java/com/MylesAndMore/tumble/api/Layers.java | 85 ++++++---------------- 6 files changed, 36 insertions(+), 145 deletions(-) diff --git a/README.md b/README.md index 185e2b9..6c19f2d 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,5 @@ -# tumble-alphatest (@MylesAndMore @CraivMan) +# tumble -please let me know if there is anything more you think we should add @CraivMan! -once this list is complete and all bugs are fixed, we *should* be ready for release... +## Overview -## generation - -- [x] layers should be able to generate w/ "clumps" of blocks; instead of only one material as a whole - - [x] the clump size should be customizable (for later); be able to set a min/max val and it will choose randomly per each clump (not in config file yet, just internally) - - *Note: this is done through the amount of times each Material shows up in the List--there's no config for it.* -- [x] make shovels generation actually work properly - - make different types of platforms (square, circle, multi-tiered, etc.); still should be pseudo-random -- [x] make snowballs generation actually work properly (shocker) - - make three layers generate (same layer types as shovels, just multiple of them) - -## game realism - -- [x] make the shovel in shovels mode not lose any durabilty -- [x] make it so that you can't move until the game begins -- [x] make the game blocks breakable very fast, but **not instantly--very important for balancing!!** - - Basically, just set a "cooldown" on both snowballs and shovels--not a long one--but one at that -- [x] add infinite snowballs in the gamemanager for tumble mode -- [x] make it so that you can't remove any of the game items from your inventory -- [x] make snowballs actually break blocks (duh) -- [x] make the randomized mode logic -- [x] make it so rounds end in a draw after 5m -- [x] make it so that players get snowballs instead of shovels in shovels rounds after 2m 30s -- [x] remove snowball knockback - -## game logic - -- [x] make a Game class and object that we can initialize a new instance of with a gameType -- [x] prevent players from joining/autojoining during a game -- [x] keep track of when someone wins; start a new round when this happens -- [x] keep track of how many wins each player has; end the game when a player reaches 3 - - [x] add a section in the config for a place to tp the winning player - - [x] add logic to do this - -## configuration/customization - -- [x] add two configs where you can: - - [x] set if you want the game to auto-start - - [x] set the amt of players you want the game to auto-start at - - [x] program the auto-start (just add an if statement on the PlayerJoin listener to run the StartGame method on a certain amt of players in the config) - -## etc - -- [x] refactor EventListener null checker code - - if (TumbleManager.getGameWorld() == null && TumbleManager.getLobbyWorld() == null) { return; } -- [x] add game music? but probably only for us; I feel like the og music must be copyrighted +Cringe diff --git a/src/main/java/com/MylesAndMore/tumble/EventListener.java b/src/main/java/com/MylesAndMore/tumble/EventListener.java index d6b3ffa..5e46e87 100644 --- a/src/main/java/com/MylesAndMore/tumble/EventListener.java +++ b/src/main/java/com/MylesAndMore/tumble/EventListener.java @@ -4,7 +4,6 @@ import java.util.Objects; import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.entity.Snowball; import org.bukkit.event.EventHandler; @@ -17,6 +16,9 @@ import org.bukkit.event.player.*; import org.bukkit.inventory.ItemStack; import org.bukkit.util.Vector; +/** + * Tumble event listener for all plugin and game-related events. + */ public class EventListener implements Listener { @EventHandler public void PlayerJoinEvent(PlayerJoinEvent event) { diff --git a/src/main/java/com/MylesAndMore/tumble/Game.java b/src/main/java/com/MylesAndMore/tumble/Game.java index 58c42a5..91c2770 100644 --- a/src/main/java/com/MylesAndMore/tumble/Game.java +++ b/src/main/java/com/MylesAndMore/tumble/Game.java @@ -17,6 +17,9 @@ 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 @@ -46,8 +49,6 @@ public class Game { private int gameID = -1; // Define a variable for the autostart PID private int autoStartID = -1; - // Define a variable for music ID - private int musicID = -1; // Define a variable to keep the list of tracks that have already played in the game List sounds = new ArrayList<>(); @@ -56,9 +57,6 @@ public class Game { // 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 lobby's players for later -// private List lobbyPlayers = TumbleManager.getPlayersInLobby(); // Make a list of the game's players for later private List gamePlayers; // Make a list of the round's players @@ -130,7 +128,6 @@ public class Game { displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1); setGamemode(gamePlayers, GameMode.SURVIVAL); gameState = "running"; - playMusic(gamePlayers, SoundCategory.NEUTRAL, 1, 1); }, 20); }, 20); }, 20); @@ -443,30 +440,6 @@ public class Game { } } - private void playMusic(@NotNull List players, @NotNull SoundCategory category, float volume, float pitch) { - if (sounds.size() == 0) { - sounds.addAll(List.of( - "minecraft:tumble.0", - "minecraft:tumble.1", - "minecraft:tumble.2", - "minecraft:tumble.3", - "minecraft:tumble.4", - "minecraft:tumble.5", - "minecraft:tumble.6", - "minecraft:tumble.7", - "minecraft:tumble.8", - "minecraft:tumble.9")); - } - String currentSong = sounds.get(Random.nextInt(sounds.size())); - for (Player aPlayer : players) { - aPlayer.playSound(aPlayer.getLocation(), currentSong, category, volume, pitch); - } - sounds.remove(currentSong); - musicID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { - playMusic(gamePlayers, SoundCategory.NEUTRAL, 1, 1); - }, 1460); - } - /** * Teleports a list of players to the specified scatter locations in the gameWorld * @param players a List of Players to teleport @@ -603,8 +576,6 @@ public class Game { displayActionbar(gamePlayers, ChatColor.BLUE + "Returning to lobby in ten seconds..."); // Wait 10s (200t), then Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(TumbleManager.getPlugin(), () -> { - // Stop music from replaying - Bukkit.getServer().getScheduler().cancelTask(musicID); // 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 diff --git a/src/main/java/com/MylesAndMore/tumble/TumbleManager.java b/src/main/java/com/MylesAndMore/tumble/TumbleManager.java index 7605717..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() { diff --git a/src/main/java/com/MylesAndMore/tumble/api/Generator.java b/src/main/java/com/MylesAndMore/tumble/api/Generator.java index 0a35767..db8bacc 100644 --- a/src/main/java/com/MylesAndMore/tumble/api/Generator.java +++ b/src/main/java/com/MylesAndMore/tumble/api/Generator.java @@ -11,6 +11,9 @@ import java.util.Collections; import java.util.List; import java.util.Random; +/** + * This class holds the methods that generate blocks in-game such as cylinders, cubiods, and clump logic. + */ public class Generator { /** * Generates a layer (bascally just a cylinder) as best as it can w/ blocks diff --git a/src/main/java/com/MylesAndMore/tumble/api/Layers.java b/src/main/java/com/MylesAndMore/tumble/api/Layers.java index dad5ea8..8818631 100644 --- a/src/main/java/com/MylesAndMore/tumble/api/Layers.java +++ b/src/main/java/com/MylesAndMore/tumble/api/Layers.java @@ -12,52 +12,24 @@ import java.util.Random; public class Layers { public Layers(){ - matList.add(gen0); - matList.add(gen1); - matList.add(gen2); - matList.add(gen3); - matList.add(gen4); - matList.add(gen5); - matList.add(gen6); - matList.add(gen7); - matList.add(gen8); - matList.add(gen9); - matList.add(gen10); - matList.add(gen12); - matList.add(gen14); - matList.add(gen15); - matList.add(gen16); - matList.add(gen0); - matList.add(gen1); - matList.add(gen2); - matList.add(gen3); - matList.add(gen4); - matList.add(gen5); - matList.add(gen6); - matList.add(gen7); - matList.add(gen8); - matList.add(gen9); - matList.add(gen10); - matList.add(gen12); - matList.add(gen14); - matList.add(gen15); - matList.add(gen16); - matList.add(gen0); - matList.add(gen1); - matList.add(gen2); - matList.add(gen3); - matList.add(gen4); - matList.add(gen5); - matList.add(gen6); - matList.add(gen7); - matList.add(gen8); - matList.add(gen9); - matList.add(gen10); - matList.add(gen12); - matList.add(gen14); - matList.add(gen15); - matList.add(gen16); - // Troll glass layer + // 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); } @@ -70,6 +42,9 @@ public class Layers { return matList.get(random.nextInt(matList.size())); } + // Define the list that will store the material lists + private final List> matList = new ArrayList<>(); + // Begin lists @@ -287,14 +262,6 @@ public class Layers { 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); }}; @@ -307,14 +274,6 @@ public class Layers { add(Material.BRICK_STAIRS); }}; - private final List gen14 = new ArrayList<>() {{ - add(Material.LECTERN); - add(Material.OBSIDIAN); - add(Material.SPONGE); - add(Material.BEEHIVE); - add(Material.DRIED_KELP_BLOCK); - }}; - private final List gen15 = new ArrayList<>() {{ add(Material.SANDSTONE); add(Material.SANDSTONE_SLAB); @@ -338,6 +297,4 @@ public class Layers { add(Material.JUNGLE_TRAPDOOR); }}; - private final List> matList = new ArrayList<>(); - } -- cgit v1.2.3 From fca9ec1f9235fe8f9c2941c99997f11c88177cce Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Mon, 12 Dec 2022 15:14:53 -0600 Subject: begin the (actual) readme --- README.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6c19f2d..8559810 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,22 @@ ## Overview -Cringe +Tumble is a Spigot/Paper plugin that aims to recreate the Tumble minigame from the bygone era of the Minecraft Legacy Console Editions. + +## What *is* Tumble? + +If you've never heard of it, [Tumble](https://minecraft-archive.fandom.com/wiki/Tumble_Mode) is a twist on the classic Minecraft minigame of spleef, where the objective is to break the blocks under your opponents. But in Tumble, you play on randomly generated layers of blocks, using shovels, snowballs, or both to try and eliminate your opponents. + +## Features + +- 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 + +## Setup + +... -- cgit v1.2.3 From ae3d7842ba4f261add8d5beb207d613515ee6602 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Tue, 13 Dec 2022 11:49:07 -0600 Subject: update versioning, config, and readme for pre-release --- README.md | 53 ++++++++++++++++++++++++++++++++++++++++++- src/main/resources/config.yml | 12 +++++----- src/main/resources/plugin.yml | 2 +- 3 files changed, 59 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 8559810..909880e 100644 --- a/README.md +++ b/README.md @@ -20,4 +20,55 @@ If you've never heard of it, [Tumble](https://minecraft-archive.fandom.com/wiki/ ## Setup -... +1. Simply [download]() **add link to download** the plugin's JAR file and place it in your server's plugins directory. + + - *Note: Multiverse is also required for the plugin to run, you may download it [here](https://www.spigotmc.org/resources/multiverse-core.390/).* + +2. Make sure that you have at least two worlds in your world directory! One is for your lobby world, and the other is for your game arena. + + - If you would like an experience similar to the original game, see [my guide]() **add this guide** for using the original worlds. + +3. Start your server. The plugin will generate a couple of warnings, these are normal. +4. Ensure that you have imported your worlds into Multiverse. This can be done with the command ```/mv import normal```. +5. Now you need to tell Tumble which world is your lobby and which world is your game arena. You can do this with ```/tumble:link lobby``` and ```/tumble:link game``` respectively. +6. You're done! You can now start games with the command ```/tumble:start```. + +Scroll down for more options to configure your game. + +## Commands + +- ```/tumble:reload``` + + - *Description:* Reloads the plugin's configuration. + - *Usage:* ```/tumble:reload``` + - *Permission:* ```tumble.reload``` +- ```/tumble:link``` + - *Description:* Links a world on the server as a lobby or game world. + - *Usage:* ```/tumble:link (lobby|game)``` + - *Permission:* ```tumble.link``` +- ```/tumble:start``` + - *Description:* Force starts a Tumble match (with an optional game type). + - *Usage:* ```/tumble:start [game-type]``` + - *Permission:* ```tumble.start``` +- ```/tumble:winlocation``` + - *Description:* Sets the location to teleport the winning player of a game. Uses the player's location if no arguments are specified. + - *Usage:* ```/tumble:winlocation [x] [y] [z]``` + - *Permission:* ```tumble.winlocation``` +- ```/tumble:autostart``` + - *Description:* Configures the auto start functions of Tumble. + - *Usage:* ```/tumble:autostart [enable|disable]``` + - *Permission:* ```tumble.autostart``` + +## Configuration + +- ```gameMode``` + - Customize the default game mode of Tumble. + - Acceptable options include: shovels, snowballs, mixed + - *Default:* ```mixed``` + +- ```hideJoinLeaveMessages``` + - Hides join/leave messages in public chat. + - *Default:* ```false``` + +- ```permissionMessage``` + - Customize the message that displays when the player does not have permission to execute a command from this plugin. diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index bc68c35..ee2a2c7 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,3 +1,8 @@ +# Customize the default game mode of Tumble +# Acceptable options include: shovels, snowballs, mixed +# Default is mixed +gameMode: mixed + # Hides join/leave messages in public chat # Default is false hideJoinLeaveMessages: false @@ -5,13 +10,8 @@ hideJoinLeaveMessages: false # Customize the message that displays when the player does not have permission to execute a command from this plugin permissionMessage: You do not have permission to perform this command! -# Customize the game mode of Tumble -# Acceptable options include: shovels, snowballs, mixed -# Default is mixed -gameMode: mixed - # Customize the auto start feature of Tumble -# Defaults are disabled and two players +# Defaults are false and two players # Players can be up to 8 autoStart: enabled: false diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index ac394bf..c78eece 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: 0.0.1-SNAPSHOT +version: 1.0.0 description: 'A Minecraft: Java Edition plugin recreating the Tumble minigame from Minecraft Legacy Console Edition.' api-version: 1.19 load: STARTUP -- cgit v1.2.3 From 2aef525320231266c74e7611414eaca5ecd67644 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Tue, 13 Dec 2022 11:50:40 -0600 Subject: Create og-guide.md --- og-guide.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 og-guide.md diff --git a/og-guide.md b/og-guide.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/og-guide.md @@ -0,0 +1 @@ + -- cgit v1.2.3 From 260b4e8985074847ac4e825845a997618e3556fb Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Tue, 13 Dec 2022 13:03:55 -0600 Subject: write og-guide and (almost) finish readme --- README.md | 7 ++++--- og-guide.md | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 909880e..1205386 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# tumble +# tumble ## Overview @@ -26,12 +26,13 @@ If you've never heard of it, [Tumble](https://minecraft-archive.fandom.com/wiki/ 2. Make sure that you have at least two worlds in your world directory! One is for your lobby world, and the other is for your game arena. - - If you would like an experience similar to the original game, see [my guide]() **add this guide** for using the original worlds. + - If you would like an experience similar to the original game, see [my guide](https://github.com/MylesAndMore/tumble/blob/main/og-guide.md) for using the original worlds. 3. Start your server. The plugin will generate a couple of warnings, these are normal. 4. Ensure that you have imported your worlds into Multiverse. This can be done with the command ```/mv import normal```. 5. Now you need to tell Tumble which world is your lobby and which world is your game arena. You can do this with ```/tumble:link lobby``` and ```/tumble:link game``` respectively. -6. You're done! You can now start games with the command ```/tumble:start```. +6. **VERY IMPORTANT:** The plugin will teleport players to the world spawn point of each world, and generate the game's blocks around the spawn point of the game world. Ensure that your spawn points are clear of any obstructions, and that a 20x20x20 cube is cleared out from the spawn of whatever game world you are using. **Any blocks in this area will be destroyed when the game begins.** +7. You're done! You can now start games with the command ```/tumble:start```. Scroll down for more options to configure your game. diff --git a/og-guide.md b/og-guide.md index 8b13789..314ddf8 100644 --- a/og-guide.md +++ b/og-guide.md @@ -1 +1,33 @@ +# tumble +## Guide for original worlds + +In this guide, I'll go over how to set up the Tumble plugin with the original game worlds from the Legacy Console Editions. + +## Steps + +1. Download the worlds and unzip them into your server's main/root directory. **Ensure you download the Java and not the Bedrock versions**! +A huge thanks to *Catmanjoe* for porting these worlds! This game would not be the same without you! + + - [Lobby (new edition)](https://mcpedl.com/mc-2017-new-mini-games-lobby-download-map/) + - [Lobby (old edition)](https://mcpedl.com/minecraft-2016-classic-mini-games-lobby-map/) + - [Arena](https://www.planetminecraft.com/project/minecraft-2016-classic-mini-games-lobby-download-bedrock-edition/) +2. Take note of the names of the world folders (you may rename them), we will need this in a moment. +3. Start and join your server. +4. Import both worlds into Multiverse. You can do this by running the command ```/mv import normal``` for both worlds. +5. Now you can link each world! Do this with ```/tumble:link lobby``` and ```/tumble:link game``` respectively. +6. Teleport to your new lobby world by using ```/mvtp ```. +7. Set the correct spawn location in this world using ```/setworlspawn```. For me, the correct coordinates were ```/setworldspawn place holder L```, but your results may vary. +8. Set the location that the winner will be teleported using ```tumble:winloc```. Again, the correct coordinates were ```tumble:winloc wait no u``` in my case. +9. Now, teleport to the game world. Use ```/mvtp ```. +10. Set the correct spawn point of this world. This is also where the game will generate its blocks. My preferred position is ```/setworldspawn 0 60 0```, but you may place the spawn whereever you like. + +You're done! + +## Continuation + +With this, the setup for this plugin is complete, but there still may be more for you to do. There are other plugins out there to fine-tune your experience even more. Plugins like [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/) can protect players from breaking blocks in the lobby and reset any redstone they activated, while others like [ViaVersion](https://www.spigotmc.org/resources/viaversion.19254/) can allow you to play Tumble from your favorite Minecraft version (yes, you, 1.8.9 players). + +Whatever you choose, the experience is up to you. + +Happy playing! -- cgit v1.2.3 From b6726a7e811877a7e5835509a5cd6f8b94de7941 Mon Sep 17 00:00:00 2001 From: Myles <43725835+MylesAndMore@users.noreply.github.com> Date: Tue, 13 Dec 2022 19:18:49 +0000 Subject: add download link and sync build version --- README.md | 6 +++++- build.gradle | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1205386..267a4b0 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ If you've never heard of it, [Tumble](https://minecraft-archive.fandom.com/wiki/ ## Setup -1. Simply [download]() **add link to download** the plugin's JAR file and place it in your server's plugins directory. +1. Simply [download](https://github.com/MylesAndMore/tumble/releases/tag/stable) the plugin's JAR file and place it in your server's plugins directory. - *Note: Multiverse is also required for the plugin to run, you may download it [here](https://www.spigotmc.org/resources/multiverse-core.390/).* @@ -73,3 +73,7 @@ Scroll down for more options to configure your game. - ```permissionMessage``` - Customize the message that displays when the player does not have permission to execute a command from this plugin. + +## 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/tumble/issues/new)! diff --git a/build.gradle b/build.gradle index 019bafd..a7f815e 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ java { } group 'tumble' -version '0.0.1-SNAPSHOT' +version '1.0.0' repositories { // Use Maven Central for resolving dependencies. -- cgit v1.2.3