diff options
Diffstat (limited to 'src')
27 files changed, 972 insertions, 488 deletions
diff --git a/src/main/java/com/MylesAndMore/Tumble/Main.java b/src/main/java/com/MylesAndMore/Tumble/Main.java index 274765e..f098a12 100644 --- a/src/main/java/com/MylesAndMore/Tumble/Main.java +++ b/src/main/java/com/MylesAndMore/Tumble/Main.java @@ -1,8 +1,10 @@ package com.MylesAndMore.Tumble; import com.MylesAndMore.Tumble.commands.*; -import com.MylesAndMore.Tumble.plugin.ConfigManager; +import com.MylesAndMore.Tumble.config.ArenaManager; +import com.MylesAndMore.Tumble.config.ConfigManager; +import com.MylesAndMore.Tumble.config.LanguageManager; import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; @@ -16,17 +18,14 @@ public class Main extends JavaPlugin{ @Override public void onEnable() { plugin = this; + new ArenaManager(); + new ConfigManager(); + new LanguageManager(); - Objects.requireNonNull(this.getCommand("tumble-reload")).setExecutor(new Reload()); - Objects.requireNonNull(this.getCommand("tumble-config")).setExecutor(new Config()); - Objects.requireNonNull(this.getCommand("tumble-forcestart")).setExecutor(new ForceStart()); - Objects.requireNonNull(this.getCommand("tumble-join")).setExecutor(new Join()); - Objects.requireNonNull(this.getCommand("tumble-leave")).setExecutor(new Leave()); - Objects.requireNonNull(this.getCommand("tumble-forcestop")).setExecutor(new ForceStop()); + Objects.requireNonNull(this.getCommand("tumble")).setExecutor(new Tumble()); new Metrics(this, 16940); this.saveDefaultConfig(); // Saves the default config file (packaged in the JAR) if we haven't already - ConfigManager.readConfig(); Bukkit.getServer().getLogger().info("[Tumble] Tumble successfully enabled!"); } diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/Config.java b/src/main/java/com/MylesAndMore/Tumble/commands/Config.java deleted file mode 100644 index 5fc2de6..0000000 --- a/src/main/java/com/MylesAndMore/Tumble/commands/Config.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.MylesAndMore.Tumble.commands; - -import com.MylesAndMore.Tumble.game.Arena; -import com.MylesAndMore.Tumble.plugin.ConfigManager; -import org.bukkit.ChatColor; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class Config implements CommandExecutor, TabCompleter { - @Override - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { - if (!(sender instanceof Player)) { - sender.sendMessage(ChatColor.RED + "This cannot be run by the console"); - return false; - } - - if (!sender.hasPermission("tumble.config")) { - sender.sendMessage(ChatColor.RED + "You do not have permission to perform this command!"); - return false; - } - - if (args.length < 2 || args[0] == null || args[1] == null) { - sender.sendMessage(ChatColor.RED + "Missing arguments"); - return false; - } - - switch (args[0]) { - case "add" -> { - String arenaName = args[1]; - ConfigManager.arenas.put(arenaName, new Arena(arenaName, ((Player)sender).getLocation(), null)); - sender.sendMessage(ChatColor.GREEN + "Arena added."); - } - case "set" -> { - String world = args[1]; - if (ConfigManager.arenas.containsKey(world)) { - ConfigManager.arenas.get(world).location = ((Player)sender).getLocation(); - } - else if (world.equals("waitArea")) { - ConfigManager.waitArea = ((Player)sender).getLocation(); - } - else if (world.equals("lobbySpawn")) { - ConfigManager.lobby = ((Player)sender).getLocation(); - } - else if (world.equals("winnerLobbySpawn")) { - ConfigManager.winnerLobby = ((Player)sender).getLocation(); - } - else { - sender.sendMessage(ChatColor.RED + "Invalid parameter"); - return false; - } - sender.sendMessage(ChatColor.GREEN + "Location set."); - } - case "disable" -> { - String world = args[1]; - if (world.equals("waitArea")) { - ConfigManager.waitArea = null; - } - else if (world.equals("winnerLobbySpawn")) { - ConfigManager.winnerLobby = null; - } - else { - sender.sendMessage(ChatColor.RED + "Invalid parameter"); - return false; - } - sender.sendMessage(ChatColor.GREEN + "World disabled."); - } - case "remove" -> { - String world = args[1]; - if (ConfigManager.arenas.containsKey(world)) { - ConfigManager.arenas.remove(world); - } - else { - sender.sendMessage(ChatColor.RED + "Invalid parameter"); - return false; - } - sender.sendMessage(ChatColor.GREEN + "Location set"); - } - default -> { - sender.sendMessage(ChatColor.RED + "Invalid parameter"); - return false; - } - } - - ConfigManager.WriteConfig(); - sender.sendMessage(ChatColor.GREEN + "Wrote changes to file."); - return true; - } - - @Override - public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { - if (args.length == 1) { - return new ArrayList<>(Arrays.asList("add", "set", "disable", "remove")); - } - if (args.length == 2) { - switch (args[0]) { - case "set" -> { - ArrayList<String> temp = new ArrayList<>(ConfigManager.arenas.keySet()); - temp.addAll(Arrays.asList("waitArea", "lobbySpawn", "winnerLobbySpawn")); - return temp; - } - case "disable" -> { - return Arrays.asList("waitArea", "winnerLobbySpawn"); - } - case "delete" -> { - return ConfigManager.arenas.keySet().stream().toList(); - } - default -> { - return new ArrayList<>(); - } - } - } - return new ArrayList<>(); - } -} diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/Create.java b/src/main/java/com/MylesAndMore/Tumble/commands/Create.java new file mode 100644 index 0000000..3340cc6 --- /dev/null +++ b/src/main/java/com/MylesAndMore/Tumble/commands/Create.java @@ -0,0 +1,44 @@ +package com.MylesAndMore.Tumble.commands; + +import com.MylesAndMore.Tumble.game.Arena; +import com.MylesAndMore.Tumble.config.LanguageManager; +import com.MylesAndMore.Tumble.config.ArenaManager; +import com.MylesAndMore.Tumble.plugin.SubCommand; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class Create implements SubCommand, CommandExecutor, TabCompleter { + @Override + public String getCommandName() { + return "create"; + } + + @Override + public String getPermission() { + return "tumble.create"; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (args.length == 0 || args[0] == null || args[0].isEmpty()) { + sender.sendMessage(LanguageManager.fromKey("missing-arena-parameter")); + return false; + } + + String arenaName = args[0]; + ArenaManager.arenas.put(arenaName, new Arena(arenaName)); + sender.sendMessage(LanguageManager.fromKey("create-success")); + return true; + } + + @Override + public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + return Collections.emptyList(); + } +} diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/ForceStart.java b/src/main/java/com/MylesAndMore/Tumble/commands/ForceStart.java index bdead44..c8042bc 100644 --- a/src/main/java/com/MylesAndMore/Tumble/commands/ForceStart.java +++ b/src/main/java/com/MylesAndMore/Tumble/commands/ForceStart.java @@ -1,8 +1,9 @@ package com.MylesAndMore.Tumble.commands; import com.MylesAndMore.Tumble.game.Game; -import com.MylesAndMore.Tumble.plugin.ConfigManager; -import org.bukkit.ChatColor; +import com.MylesAndMore.Tumble.config.LanguageManager; +import com.MylesAndMore.Tumble.config.ArenaManager; +import com.MylesAndMore.Tumble.plugin.SubCommand; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -13,36 +14,42 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; -public class ForceStart implements CommandExecutor, TabCompleter { +public class ForceStart implements SubCommand, CommandExecutor, TabCompleter { + @Override - public boolean onCommand(CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + public String getCommandName() { + return "forceStart"; + } - if (!sender.hasPermission("tumble.forcestart")) { - sender.sendMessage(ChatColor.RED + "You do not have permission to perform this command!"); - return false; - } + @Override + public String getPermission() { + return "tumble.forceStart"; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { Game game; if (args.length < 1 || args[0] == null) { - game = ConfigManager.findGamePlayerIsIn((Player)sender); + game = ArenaManager.findGamePlayerIsIn((Player)sender); if (game == null) { - sender.sendMessage(ChatColor.RED + "Missing arena name"); + sender.sendMessage(LanguageManager.fromKey("missing-arena-parameter")); return false; } } else { - game = ConfigManager.arenas.get(args[0]).game; + game = ArenaManager.arenas.get(args[0]).game; } game.gameStart(); - sender.sendMessage(ChatColor.GREEN + "Starting game"); + sender.sendMessage(LanguageManager.fromKey("forcestart-success")); return true; } @Override public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { if (args.length == 1) { - return ConfigManager.arenas.keySet().stream().toList(); + return ArenaManager.arenas.keySet().stream().toList(); } return new ArrayList<>(); } diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/ForceStop.java b/src/main/java/com/MylesAndMore/Tumble/commands/ForceStop.java index ddd5826..96e8334 100644 --- a/src/main/java/com/MylesAndMore/Tumble/commands/ForceStop.java +++ b/src/main/java/com/MylesAndMore/Tumble/commands/ForceStop.java @@ -1,8 +1,9 @@ package com.MylesAndMore.Tumble.commands; import com.MylesAndMore.Tumble.game.Game; -import com.MylesAndMore.Tumble.plugin.ConfigManager; -import org.bukkit.ChatColor; +import com.MylesAndMore.Tumble.config.LanguageManager; +import com.MylesAndMore.Tumble.config.ArenaManager; +import com.MylesAndMore.Tumble.plugin.SubCommand; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -13,41 +14,47 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; -public class ForceStop implements CommandExecutor, TabCompleter { +public class ForceStop implements SubCommand, CommandExecutor, TabCompleter { + @Override - public boolean onCommand(CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + public String getCommandName() { + return "forcestop"; + } - if (!sender.hasPermission("tumble.forcestop")) { - sender.sendMessage(ChatColor.RED + "You do not have permission to perform this command!"); - return false; - } + @Override + public String getPermission() { + return "tumble.forcestop"; + } + + @Override + public boolean onCommand(CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { Game game; if (args.length < 1 || args[0] == null) { - game = ConfigManager.findGamePlayerIsIn((Player)sender); + game = ArenaManager.findGamePlayerIsIn((Player)sender); if (game == null) { - sender.sendMessage(ChatColor.RED + "Missing arena name"); + sender.sendMessage(LanguageManager.fromKey("missing-arena-parameter")); return false; } } else { - game = ConfigManager.arenas.get(args[0]).game; + game = ArenaManager.arenas.get(args[0]).game; } if (game == null) { - sender.sendMessage(ChatColor.RED + "No game is currently running in this arena"); + sender.sendMessage(LanguageManager.fromKey("no-game-in-arena")); return false; } game.gameEnd(); - sender.sendMessage(ChatColor.GREEN + "Game stopped."); + sender.sendMessage(LanguageManager.fromKey("forcestop-success")); return true; } @Override public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { if (args.length == 1) { - return ConfigManager.arenas.keySet().stream().toList(); + return ArenaManager.arenas.keySet().stream().toList(); } return new ArrayList<>(); } diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/Join.java b/src/main/java/com/MylesAndMore/Tumble/commands/Join.java index de44da1..a887c99 100644 --- a/src/main/java/com/MylesAndMore/Tumble/commands/Join.java +++ b/src/main/java/com/MylesAndMore/Tumble/commands/Join.java @@ -1,10 +1,12 @@ package com.MylesAndMore.Tumble.commands; import com.MylesAndMore.Tumble.game.Arena; -import com.MylesAndMore.Tumble.plugin.ConfigManager; +import com.MylesAndMore.Tumble.config.LanguageManager; +import com.MylesAndMore.Tumble.config.ArenaManager; import com.MylesAndMore.Tumble.game.Game; import com.MylesAndMore.Tumble.plugin.GameState; import com.MylesAndMore.Tumble.plugin.GameType; +import com.MylesAndMore.Tumble.plugin.SubCommand; import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; @@ -19,35 +21,41 @@ import java.util.List; import java.util.Objects; import java.util.stream.Collectors; -public class Join implements CommandExecutor, TabCompleter { +public class Join implements SubCommand, CommandExecutor, TabCompleter { + + @Override + public String getCommandName() { + return "join"; + } + + @Override + public String getPermission() { + return "tumble.join"; + } + @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { if (!(sender instanceof Player)) { - sender.sendMessage(ChatColor.RED + "This cannot be run by the console"); - return false; - } - - if (!sender.hasPermission("tumble.join")) { - sender.sendMessage(ChatColor.RED + "You do not have permission to perform this command!"); + sender.sendMessage(LanguageManager.fromKey("not-for-console")); return false; } - if (ConfigManager.findGamePlayerIsIn((Player)sender) != null) { - sender.sendMessage(ChatColor.RED + "You are already in a game! Leave it to join another one"); + if (ArenaManager.findGamePlayerIsIn((Player)sender) != null) { + sender.sendMessage(LanguageManager.fromKey("already-in-game")); } if (args.length < 1 || args[0] == null) { - sender.sendMessage(ChatColor.RED + "Missing arena name"); + sender.sendMessage(LanguageManager.fromKey("missing-arena-parameter")); return false; } String arenaName = args[0]; - if (!ConfigManager.arenas.containsKey(arenaName)) + if (!ArenaManager.arenas.containsKey(arenaName)) { - sender.sendMessage(ChatColor.RED + "This arena does not exist"); + sender.sendMessage(LanguageManager.fromKey("invalid-arena").replace("%arena%", arenaName)); return false; } - Arena arena = ConfigManager.arenas.get(arenaName); + Arena arena = ArenaManager.arenas.get(arenaName); Game game; if (args.length < 2 || args[1] == null) { @@ -66,7 +74,7 @@ public class Join implements CommandExecutor, TabCompleter { case "snowballs", "snowball" -> type = GameType.SNOWBALLS; case "mix", "mixed" -> type = GameType.MIXED; default -> { - sender.sendMessage(ChatColor.RED + "Invalid game type"); + sender.sendMessage(LanguageManager.fromKey("invalid-type")); return false; } } @@ -80,26 +88,30 @@ public class Join implements CommandExecutor, TabCompleter { game = arena.game; } else { - sender.sendMessage(ChatColor.RED + "A game of "+type+" is currently taking place in this arena, choose another arena or join it with /tumble:join "+arena.name+" "+type); + sender.sendMessage(LanguageManager.fromKey("another-type-in-arena") + .replace("%type%",type.toString()) + .replace("%arena%",arenaName)); return false; } } } if (game.gameState != GameState.WAITING) { - sender.sendMessage(ChatColor.RED + "This game is still in progress, wait until it finishes or join another game"); + sender.sendMessage(LanguageManager.fromKey("game-in-progress")); return false; } game.addPlayer((Player)sender); - sender.sendMessage(ChatColor.GREEN + "Joined game " + arena.name + " - " + game.type); + sender.sendMessage(LanguageManager.fromKey("join-success") + .replace("%type%", game.type.toString()) + .replace("%arena%", arena.name)); return true; } @Override public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { if (args.length == 1) { - return ConfigManager.arenas.keySet().stream().toList(); + return ArenaManager.arenas.keySet().stream().toList(); } if (args.length == 2) { return Arrays.stream(GameType.values()).map(Objects::toString).collect(Collectors.toList()); diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/Leave.java b/src/main/java/com/MylesAndMore/Tumble/commands/Leave.java index 1d00ca4..0250cc6 100644 --- a/src/main/java/com/MylesAndMore/Tumble/commands/Leave.java +++ b/src/main/java/com/MylesAndMore/Tumble/commands/Leave.java @@ -1,8 +1,9 @@ package com.MylesAndMore.Tumble.commands; import com.MylesAndMore.Tumble.game.Game; -import com.MylesAndMore.Tumble.plugin.ConfigManager; -import org.bukkit.ChatColor; +import com.MylesAndMore.Tumble.config.LanguageManager; +import com.MylesAndMore.Tumble.config.ArenaManager; +import com.MylesAndMore.Tumble.plugin.SubCommand; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -13,28 +14,36 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; -public class Leave implements CommandExecutor, TabCompleter { +public class Leave implements SubCommand, CommandExecutor, TabCompleter { + + @Override + public String getCommandName() { + return "leave"; + } + + @Override + public String getPermission() { + return "tumble.leave"; + } + @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { if (!(sender instanceof Player)) { - sender.sendMessage(ChatColor.RED + "This cannot be run by the console"); - return false; - } - - if (!sender.hasPermission("tumble.leave")) { - sender.sendMessage(ChatColor.RED + "You do not have permission to perform this command!"); + sender.sendMessage(LanguageManager.fromKey("not-for-console")); return false; } - Game game = ConfigManager.findGamePlayerIsIn((Player)sender); + Game game = ArenaManager.findGamePlayerIsIn((Player)sender); if (game == null) { - sender.sendMessage(ChatColor.RED + "You are not in a game."); + sender.sendMessage(LanguageManager.fromKey("no-game-in-arena")); return false; } game.removePlayer((Player) sender); - sender.sendMessage(ChatColor.GREEN + "Game left."); + sender.sendMessage(LanguageManager.fromKey("leave-success") + .replace("%arena%", game.arena.name) + .replace("%type%", game.type.toString())); return true; } diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/Reload.java b/src/main/java/com/MylesAndMore/Tumble/commands/Reload.java index ca67a2e..66535d5 100644 --- a/src/main/java/com/MylesAndMore/Tumble/commands/Reload.java +++ b/src/main/java/com/MylesAndMore/Tumble/commands/Reload.java @@ -1,8 +1,9 @@ package com.MylesAndMore.Tumble.commands; import com.MylesAndMore.Tumble.game.Arena; -import com.MylesAndMore.Tumble.plugin.ConfigManager; -import org.bukkit.ChatColor; +import com.MylesAndMore.Tumble.config.LanguageManager; +import com.MylesAndMore.Tumble.config.ArenaManager; +import com.MylesAndMore.Tumble.plugin.SubCommand; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -14,23 +15,29 @@ import java.util.List; import static com.MylesAndMore.Tumble.Main.plugin; -public class Reload implements CommandExecutor, TabCompleter { +public class Reload implements SubCommand, CommandExecutor, TabCompleter { @Override - public boolean onCommand(CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { - if (!sender.hasPermission("tumble.reload")) { - sender.sendMessage(ChatColor.RED + "You do not have permission to perform this command!"); - return false; - } + public String getCommandName() { + return "reload"; + } + + @Override + public String getPermission() { + return "tumble.reload"; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { - for (Arena a : ConfigManager.arenas.values()) { + for (Arena a : ArenaManager.arenas.values()) { if (a.game != null) { a.game.gameEnd(); } } plugin.onEnable(); - sender.sendMessage(ChatColor.GREEN + "Tumble configuration reloaded. Check console for errors."); + sender.sendMessage(LanguageManager.fromKey("reload-success")); return true; } diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/Remove.java b/src/main/java/com/MylesAndMore/Tumble/commands/Remove.java new file mode 100644 index 0000000..118aa77 --- /dev/null +++ b/src/main/java/com/MylesAndMore/Tumble/commands/Remove.java @@ -0,0 +1,53 @@ +package com.MylesAndMore.Tumble.commands; + +import com.MylesAndMore.Tumble.config.LanguageManager; +import com.MylesAndMore.Tumble.config.ArenaManager; +import com.MylesAndMore.Tumble.plugin.SubCommand; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class Remove implements SubCommand, CommandExecutor, TabCompleter { + + @Override + public String getCommandName() { + return "remove"; + } + + @Override + public String getPermission() { + return "tumble.remove"; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (args.length == 0 || args[0] == null || args[0].isEmpty()) { + sender.sendMessage(LanguageManager.fromKey("missing-arena-parameter")); + return false; + } + String arenaName = args[0]; + + if (!ArenaManager.arenas.containsKey(arenaName)) { + sender.sendMessage(LanguageManager.fromKey("invalid-arena").replace("%arena%",arenaName)); + return false; + } + + ArenaManager.arenas.remove(arenaName); + sender.sendMessage(LanguageManager.fromKey("set-success")); + return true; + } + + @Override + public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (args.length == 1) { + return ArenaManager.arenas.keySet().stream().toList(); + } + + return Collections.emptyList(); + } +} diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/SetGameSpawn.java b/src/main/java/com/MylesAndMore/Tumble/commands/SetGameSpawn.java new file mode 100644 index 0000000..62d22f8 --- /dev/null +++ b/src/main/java/com/MylesAndMore/Tumble/commands/SetGameSpawn.java @@ -0,0 +1,60 @@ +package com.MylesAndMore.Tumble.commands; + +import com.MylesAndMore.Tumble.game.Arena; +import com.MylesAndMore.Tumble.config.LanguageManager; +import com.MylesAndMore.Tumble.config.ArenaManager; +import com.MylesAndMore.Tumble.plugin.SubCommand; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class SetGameSpawn implements SubCommand, CommandExecutor, TabCompleter { + @Override + public String getCommandName() { + return "setGameSpawn"; + } + + @Override + public String getPermission() { + return "tumble.setGameSpawn"; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage(LanguageManager.fromKey("not-for-console")); + return false; + } + + if (args.length == 0 || args[0] == null || args[0].isEmpty()) { + sender.sendMessage(LanguageManager.fromKey("missing-arena-parameter")); + return false; + } + String arenaName = args[0]; + + if (!ArenaManager.arenas.containsKey(arenaName)) { + sender.sendMessage(LanguageManager.fromKey("invalid-arena").replace("%arena%",arenaName)); + return false; + } + Arena arena = ArenaManager.arenas.get(arenaName); + + arena.gameSpawn = ((Player)sender).getLocation(); + sender.sendMessage(LanguageManager.fromKey("set-success")); + return true; + } + + @Override + public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (args.length == 1) { + return ArenaManager.arenas.keySet().stream().toList(); + } + + return Collections.emptyList(); + } +} diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/SetKillYCordinate.java b/src/main/java/com/MylesAndMore/Tumble/commands/SetKillYCordinate.java new file mode 100644 index 0000000..0be156f --- /dev/null +++ b/src/main/java/com/MylesAndMore/Tumble/commands/SetKillYCordinate.java @@ -0,0 +1,61 @@ +package com.MylesAndMore.Tumble.commands; + +import com.MylesAndMore.Tumble.game.Arena; +import com.MylesAndMore.Tumble.config.LanguageManager; +import com.MylesAndMore.Tumble.config.ArenaManager; +import com.MylesAndMore.Tumble.plugin.SubCommand; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class SetKillYCordinate implements SubCommand, CommandExecutor, TabCompleter { + + @Override + public String getCommandName() { + return "setKillYLevel"; + } + + @Override + public String getPermission() { + return "tumble.setKillYLevel"; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage(LanguageManager.fromKey("not-for-console")); + return false; + } + + if (args.length == 0 || args[0] == null || args[0].isEmpty()) { + sender.sendMessage(LanguageManager.fromKey("missing-arena-parameter")); + return false; + } + String arenaName = args[0]; + + if (!ArenaManager.arenas.containsKey(arenaName)) { + sender.sendMessage(LanguageManager.fromKey("invalid-arena").replace("%arena%",arenaName)); + return false; + } + Arena arena = ArenaManager.arenas.get(arenaName); + + arena.killAtY = ((int) ((Player) sender).getLocation().getY()); + sender.sendMessage(LanguageManager.fromKey("set-success")); + return true; + } + + @Override + public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (args.length == 1) { + return ArenaManager.arenas.keySet().stream().toList(); + } + + return Collections.emptyList(); + } +} diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/SetLobby.java b/src/main/java/com/MylesAndMore/Tumble/commands/SetLobby.java new file mode 100644 index 0000000..dbb6b53 --- /dev/null +++ b/src/main/java/com/MylesAndMore/Tumble/commands/SetLobby.java @@ -0,0 +1,60 @@ +package com.MylesAndMore.Tumble.commands; + +import com.MylesAndMore.Tumble.game.Arena; +import com.MylesAndMore.Tumble.config.LanguageManager; +import com.MylesAndMore.Tumble.config.ArenaManager; +import com.MylesAndMore.Tumble.plugin.SubCommand; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class SetLobby implements SubCommand, CommandExecutor, TabCompleter { + @Override + public String getCommandName() { + return "setLobby"; + } + + @Override + public String getPermission() { + return "tumble.setLobby"; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage(LanguageManager.fromKey("not-for-console")); + return false; + } + + if (args.length == 0 || args[0] == null || args[0].isEmpty()) { + sender.sendMessage(LanguageManager.fromKey("missing-arena-parameter")); + return false; + } + String arenaName = args[0]; + + if (!ArenaManager.arenas.containsKey(arenaName)) { + sender.sendMessage(LanguageManager.fromKey("invalid-arena").replace("%arena%",arenaName)); + return false; + } + Arena arena = ArenaManager.arenas.get(arenaName); + + arena.lobby = ((Player)sender).getLocation(); + sender.sendMessage(LanguageManager.fromKey("set-success")); + return true; + } + + @Override + public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (args.length == 1) { + return ArenaManager.arenas.keySet().stream().toList(); + } + + return Collections.emptyList(); + } +} diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/SetWaitArea.java b/src/main/java/com/MylesAndMore/Tumble/commands/SetWaitArea.java new file mode 100644 index 0000000..f789658 --- /dev/null +++ b/src/main/java/com/MylesAndMore/Tumble/commands/SetWaitArea.java @@ -0,0 +1,60 @@ +package com.MylesAndMore.Tumble.commands; + +import com.MylesAndMore.Tumble.game.Arena; +import com.MylesAndMore.Tumble.config.LanguageManager; +import com.MylesAndMore.Tumble.config.ArenaManager; +import com.MylesAndMore.Tumble.plugin.SubCommand; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class SetWaitArea implements SubCommand, CommandExecutor, TabCompleter { + @Override + public String getCommandName() { + return "setWaitArea"; + } + + @Override + public String getPermission() { + return "tumble.setWaitArea"; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage(LanguageManager.fromKey("not-for-console")); + return false; + } + + if (args.length == 0 || args[0] == null || args[0].isEmpty()) { + sender.sendMessage(LanguageManager.fromKey("missing-arena-parameter")); + return false; + } + String arenaName = args[0]; + + if (!ArenaManager.arenas.containsKey(arenaName)) { + sender.sendMessage(LanguageManager.fromKey("invalid-arena").replace("%arena%",arenaName)); + return false; + } + Arena arena = ArenaManager.arenas.get(arenaName); + + arena.waitArea = ((Player)sender).getLocation(); + sender.sendMessage(LanguageManager.fromKey("set-success")); + return true; + } + + @Override + public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (args.length == 1) { + return ArenaManager.arenas.keySet().stream().toList(); + } + + return Collections.emptyList(); + } +} diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/SetWinnerLobby.java b/src/main/java/com/MylesAndMore/Tumble/commands/SetWinnerLobby.java new file mode 100644 index 0000000..01817b0 --- /dev/null +++ b/src/main/java/com/MylesAndMore/Tumble/commands/SetWinnerLobby.java @@ -0,0 +1,60 @@ +package com.MylesAndMore.Tumble.commands; + +import com.MylesAndMore.Tumble.game.Arena; +import com.MylesAndMore.Tumble.config.LanguageManager; +import com.MylesAndMore.Tumble.config.ArenaManager; +import com.MylesAndMore.Tumble.plugin.SubCommand; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class SetWinnerLobby implements SubCommand, CommandExecutor, TabCompleter { + @Override + public String getCommandName() { + return "setWinnerLobby"; + } + + @Override + public String getPermission() { + return "tumble.setWinnerLobby"; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage(LanguageManager.fromKey("not-for-console")); + return false; + } + + if (args.length == 0 || args[0] == null || args[0].isEmpty()) { + sender.sendMessage(LanguageManager.fromKey("missing-arena-parameter")); + return false; + } + String arenaName = args[0]; + + if (!ArenaManager.arenas.containsKey(arenaName)) { + sender.sendMessage(LanguageManager.fromKey("invalid-arena").replace("%arena%",arenaName)); + return false; + } + Arena arena = ArenaManager.arenas.get(arenaName); + + arena.winnerLobby = ((Player)sender).getLocation(); + sender.sendMessage(LanguageManager.fromKey("set-success")); + return true; + } + + @Override + public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (args.length == 1) { + return ArenaManager.arenas.keySet().stream().toList(); + } + + return Collections.emptyList(); + } +} diff --git a/src/main/java/com/MylesAndMore/Tumble/commands/Tumble.java b/src/main/java/com/MylesAndMore/Tumble/commands/Tumble.java new file mode 100644 index 0000000..6e44352 --- /dev/null +++ b/src/main/java/com/MylesAndMore/Tumble/commands/Tumble.java @@ -0,0 +1,85 @@ +package com.MylesAndMore.Tumble.commands; + +import com.MylesAndMore.Tumble.config.LanguageManager; +import com.MylesAndMore.Tumble.plugin.SubCommand; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +public class Tumble implements CommandExecutor, TabCompleter { + + private static final Map<String, SubCommand> subCommands = Map.ofEntries( + CmdNameAsKey(new Create()), + CmdNameAsKey(new ForceStart()), + CmdNameAsKey(new ForceStop()), + CmdNameAsKey(new Join()), + CmdNameAsKey(new Leave()), + CmdNameAsKey(new Reload()), + CmdNameAsKey(new Remove()), + CmdNameAsKey(new SetGameSpawn()), + CmdNameAsKey(new SetKillYCordinate()), + CmdNameAsKey(new SetLobby()), + CmdNameAsKey(new SetWaitArea()), + CmdNameAsKey(new SetWinnerLobby()) + ); + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (!subCommands.containsKey(args[0])) { + sender.sendMessage(LanguageManager.fromKey("unknown-command")); + return true; + } + + var subCmd = subCommands.get(args[0]); + + if (!sender.hasPermission(subCmd.getPermission())) { + sender.sendMessage(LanguageManager.fromKey("no-permission").replace("%permission%", subCmd.getPermission())); + return false; + } + + subCmd.onCommand(sender, command, args[0], removeFirst(args)); + return true; + } + + @Override + public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (args.length == 1) { + ArrayList<String> PermittedSubCmds = new ArrayList<>(); + for (SubCommand subCmd: subCommands.values()) { + if (sender.hasPermission(subCmd.getPermission())) { + PermittedSubCmds.add(subCmd.getCommandName()); + } + } + return PermittedSubCmds; + } + + if (args.length > 1) { + if (!subCommands.containsKey(args[0])) { + return Collections.emptyList(); + } + + if (subCommands.get(args[0]) instanceof TabCompleter tcmp) { + return tcmp.onTabComplete(sender, command, args[0], removeFirst(args)); + } + else { + return null; + } + } + + return Collections.emptyList(); + } + + private String[] removeFirst(String[] arr) { + ArrayList<String> tmp = new ArrayList<>(List.of(arr)); + tmp.remove(0); + return tmp.toArray(new String[0]); + } + + private static Map.Entry<String, SubCommand> CmdNameAsKey(SubCommand s) { + return Map.entry(s.getCommandName(),s); + } +} diff --git a/src/main/java/com/MylesAndMore/Tumble/config/ArenaManager.java b/src/main/java/com/MylesAndMore/Tumble/config/ArenaManager.java new file mode 100644 index 0000000..69a6c2c --- /dev/null +++ b/src/main/java/com/MylesAndMore/Tumble/config/ArenaManager.java @@ -0,0 +1,178 @@ +package com.MylesAndMore.Tumble.config; + +import com.MylesAndMore.Tumble.game.Arena; +import com.MylesAndMore.Tumble.game.Game; +import com.MylesAndMore.Tumble.plugin.Result; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Objects; + +import static com.MylesAndMore.Tumble.Main.plugin; + +public class ArenaManager { + private static FileConfiguration config; + public static HashMap<String, Arena> arenas; + + public ArenaManager() { + String fileName = "arenas.yml"; + // create config + File customConfigFile = new File(plugin.getDataFolder(), fileName); + if (!customConfigFile.exists()) { + customConfigFile.getParentFile().mkdirs(); + plugin.saveResource(fileName, false); + } + + config = new YamlConfiguration(); + try { + config.load(customConfigFile); + } catch (IOException | InvalidConfigurationException e) { + e.printStackTrace(); + } + /* User Edit: + Instead of the above Try/Catch, you can also use + YamlConfiguration.loadConfiguration(customConfigFile) + */ + readConfig(); + } + + /** + * Reads config file and populates values above + */ + public static void readConfig() { + plugin.reloadConfig(); + + // arenas + ConfigurationSection arenasSection = config.getConfigurationSection("arenas"); + if (arenasSection == null) { + plugin.getLogger().warning("Section 'arenas' is missing from config"); + return; + } + arenas = new HashMap<>(); + for (String arenaName: arenasSection.getKeys(false)) { + + ConfigurationSection anArenaSection = arenasSection.getConfigurationSection(arenaName); + if (anArenaSection == null) { + plugin.getLogger().warning("Failed to load arena "+arenaName+": Error loading config section"); + continue; + } + + Arena arena = new Arena(arenaName); + arenas.put(arena.name, arena); + + int killAtY = anArenaSection.getInt("kill-at-y", 0); + if (killAtY != 0) { + arena.killAtY = killAtY; + } + + Result<Location> res = readWorld(anArenaSection.getConfigurationSection("game-spawn")); + if (res.success) { + arena.gameSpawn = res.value; + } + + Result<Location> lobbyRes = readWorld(anArenaSection.getConfigurationSection("lobby")); + if (lobbyRes.success) { + arena.lobby = lobbyRes.value; + } + + Result<Location> winnerLobbyRes = readWorld(anArenaSection.getConfigurationSection("winner-lobby")); + if (winnerLobbyRes.success) { + arena.winnerLobby = winnerLobbyRes.value; + } + + Result<Location> waitAreaRes = readWorld(anArenaSection.getConfigurationSection("wait-area")); + if (waitAreaRes.success) { + arena.waitArea = waitAreaRes.value; + } + + } + } + + /** + * tries to convert a config section in the following format to a world + * section: + * x: + * y: + * z: + * world: + * @param section the section in the yaml with x, y, z, and world as its children + * @return result of either: + * success = true and a world + * success = false and an error string + */ + private static Result<Location> readWorld(@Nullable ConfigurationSection section) { + + if (section == null) { + return new Result<>("Section missing from config"); + } + + double x = section.getDouble("x"); + double y = section.getDouble("y"); + double z = section.getDouble("z"); + if (x == 0 || y == 0 || z == 0) { + return new Result<>("Arena coordinates are missing or are zero. Coordinates cannot be zero."); + } + + String worldName = section.getString("world"); + if (worldName == null) { + return new Result<>("World name is missing"); + } + + World world = Bukkit.getWorld(worldName); + if (world == null) { + return new Result<>("Failed to load world " + worldName); + } + + return new Result<>(new Location(world,x,y,z)); + } + + public static void WriteConfig() { + + for (Arena arena: arenas.values()) { + WriteWorld("arenas."+arena.name+".game-spawn", arena.gameSpawn); + WriteWorld("arenas."+arena.name+".lobby", arena.lobby); + WriteWorld("arenas."+arena.name+".winner-lobby", arena.winnerLobby); + WriteWorld("arenas."+arena.name+".wait-area", arena.waitArea); + } + + plugin.saveConfig(); + + } + + private static void WriteWorld(String path, Location location) { + ConfigurationSection section = config.getConfigurationSection(path); + + if (section == null) { + section = plugin.getConfig().createSection(path); + } + + section.set("x", location.getX()); + section.set("y", location.getY()); + section.set("z", location.getZ()); + section.set("world", Objects.requireNonNull(location.getWorld()).getName()); + } + + /** + * Searches all arenas for a game that player p is in + * @param p Player to search for + * @return the game the player is in, or null if not found + */ + public static Game findGamePlayerIsIn(Player p) { + for (Arena a : arenas.values()) { + if (a.game != null && a.game.gamePlayers.contains(p)) { + return a.game; + } + } + return null; + } +} diff --git a/src/main/java/com/MylesAndMore/Tumble/config/ConfigManager.java b/src/main/java/com/MylesAndMore/Tumble/config/ConfigManager.java new file mode 100644 index 0000000..ea7414a --- /dev/null +++ b/src/main/java/com/MylesAndMore/Tumble/config/ConfigManager.java @@ -0,0 +1,23 @@ +package com.MylesAndMore.Tumble.config; + +import org.bukkit.configuration.file.FileConfiguration; + +import static com.MylesAndMore.Tumble.Main.plugin; + +public class ConfigManager { + private static FileConfiguration config; + + public static boolean HideLeaveJoin; + public static int waitDuration; + + public ConfigManager() { + config = plugin.getConfig(); + } + + public static void readConfig() { + HideLeaveJoin = config.getBoolean("hideJoinLeaveMessages", false); + waitDuration = config.getInt("wait-duration", 15); + } + + +} diff --git a/src/main/java/com/MylesAndMore/Tumble/config/LanguageManager.java b/src/main/java/com/MylesAndMore/Tumble/config/LanguageManager.java new file mode 100644 index 0000000..c050d3c --- /dev/null +++ b/src/main/java/com/MylesAndMore/Tumble/config/LanguageManager.java @@ -0,0 +1,50 @@ +package com.MylesAndMore.Tumble.config; + +import org.bukkit.ChatColor; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.awt.*; +import java.io.File; +import java.io.IOException; + +import static com.MylesAndMore.Tumble.Main.plugin; + +public class LanguageManager { + private static FileConfiguration config; + + public LanguageManager() { + String fileName = "language.yml"; + // create config + File customConfigFile = new File(plugin.getDataFolder(), fileName); + if (!customConfigFile.exists()) { + customConfigFile.getParentFile().mkdirs(); + plugin.saveResource(fileName, false); + } + + config = new YamlConfiguration(); + try { + config.load(customConfigFile); + } catch (IOException | InvalidConfigurationException e) { + e.printStackTrace(); + } + /* User Edit: + Instead of the above Try/Catch, you can also use + YamlConfiguration.loadConfiguration(customConfigFile) + */ + } + + + public static String fromKey(String key) { + return fromKeyNoPrefix("prefix") + fromKeyNoPrefix(key); + } + + public static String fromKeyNoPrefix(String key) { + String tmp = config.getString(key, "LANG_ERR"); + if (tmp.equals("LANG_ERR")) { + plugin.getLogger().severe("There was an error getting key '"+ key +"' from language.yml"); + } + return ChatColor.translateAlternateColorCodes('&',tmp); + } +} diff --git a/src/main/java/com/MylesAndMore/Tumble/game/Arena.java b/src/main/java/com/MylesAndMore/Tumble/game/Arena.java index 831f251..71849e6 100644 --- a/src/main/java/com/MylesAndMore/Tumble/game/Arena.java +++ b/src/main/java/com/MylesAndMore/Tumble/game/Arena.java @@ -8,21 +8,22 @@ import org.jetbrains.annotations.NotNull; * An arena is the world and spawn location where a game can take place. An arena can only host one game at a time. */ public class Arena { - public Game game = null; - public final World world; - public Location location; + public final String name; - public Integer killAtY; + + public Integer killAtY = null; + public Location gameSpawn = null; + public Location lobby = null; + public Location winnerLobby = null; + public Location waitArea = null; + + public Game game = null; /** * Creates a new Arena * @param name Name of the arena - * @param location Center point / spawn point. */ - public Arena(@NotNull String name, @NotNull Location location, Integer killAtY) { - this.location = location; - this.world = location.getWorld(); + public Arena(@NotNull String name) { this.name = name; - this.killAtY = killAtY; } } diff --git a/src/main/java/com/MylesAndMore/Tumble/game/EventListener.java b/src/main/java/com/MylesAndMore/Tumble/game/EventListener.java index 28fb0d8..36d02b6 100644 --- a/src/main/java/com/MylesAndMore/Tumble/game/EventListener.java +++ b/src/main/java/com/MylesAndMore/Tumble/game/EventListener.java @@ -2,7 +2,8 @@ package com.MylesAndMore.Tumble.game; import java.util.Objects; -import com.MylesAndMore.Tumble.plugin.ConfigManager; +import com.MylesAndMore.Tumble.config.ArenaManager; +import com.MylesAndMore.Tumble.config.ConfigManager; import com.MylesAndMore.Tumble.plugin.GameState; import com.MylesAndMore.Tumble.plugin.GameType; import org.bukkit.*; @@ -32,7 +33,7 @@ public class EventListener implements Listener { Game game; public EventListener(Game game) { this.game = game; - this.gameWorld = game.gameWorld; + this.gameWorld = game.arena.gameSpawn.getWorld(); } @EventHandler @@ -43,7 +44,7 @@ public class EventListener implements Listener { } if (event.getPlayer().getWorld() == gameWorld) { // Send the player back to the lobby if they try to join in the middle of a game - event.getPlayer().teleport(Objects.requireNonNull(ConfigManager.lobby)); + event.getPlayer().teleport(Objects.requireNonNull(game.arena.lobby)); } } @@ -54,7 +55,7 @@ public class EventListener implements Listener { event.setQuitMessage(null); } if (event.getPlayer().getWorld() == gameWorld) { - event.getPlayer().teleport(ConfigManager.lobby); + event.getPlayer().teleport(game.arena.lobby); game.removePlayer(event.getPlayer()); } } @@ -101,7 +102,7 @@ public class EventListener implements Listener { if (event.getEntity() instanceof Snowball) { if (event.getEntity().getShooter() instanceof Player p) { if (event.getHitBlock() != null) { - if (event.getHitBlock().getLocation().distanceSquared(Objects.requireNonNull(game.arena.location)) < 579) { + if (event.getHitBlock().getLocation().distanceSquared(Objects.requireNonNull(game.arena.gameSpawn)) < 579) { p.playEffect( event.getHitBlock().getLocation(), Effect.STEP_SOUND, @@ -209,7 +210,7 @@ public class EventListener implements Listener { public void PlayerRespwanEvent(PlayerRespawnEvent event) { // Make sure players respawn in the correct location if (game.gamePlayers.contains(event.getPlayer())) { - event.setRespawnLocation(game.arena.location); + event.setRespawnLocation(game.arena.gameSpawn); } } diff --git a/src/main/java/com/MylesAndMore/Tumble/game/Game.java b/src/main/java/com/MylesAndMore/Tumble/game/Game.java index 113a5cd..dd13b31 100644 --- a/src/main/java/com/MylesAndMore/Tumble/game/Game.java +++ b/src/main/java/com/MylesAndMore/Tumble/game/Game.java @@ -1,6 +1,8 @@ package com.MylesAndMore.Tumble.game; -import com.MylesAndMore.Tumble.plugin.ConfigManager; +import com.MylesAndMore.Tumble.config.ArenaManager; +import com.MylesAndMore.Tumble.config.ConfigManager; +import com.MylesAndMore.Tumble.config.LanguageManager; import com.MylesAndMore.Tumble.plugin.GameState; import com.MylesAndMore.Tumble.plugin.GameType; import net.md_5.bungee.api.ChatMessageType; @@ -25,7 +27,6 @@ public class Game { public final GameType type; public final Arena arena; - public final World gameWorld; private final Location gameSpawn; public final List<Player> gamePlayers = new ArrayList<>(); private final HashMap<Player, Integer> gameWins = new HashMap<>(); @@ -40,8 +41,7 @@ public class Game { public Game(@NotNull Arena arena, @NotNull GameType type) { this.arena = arena; this.type = type; - this.gameWorld = arena.world; - this.gameSpawn = arena.location; + this.gameSpawn = arena.gameSpawn; } @@ -61,6 +61,10 @@ public class Game { eventListener = new EventListener(this); Bukkit.getServer().getPluginManager().registerEvents(eventListener, plugin); + for (Player p : gamePlayers) { + inventories.put(p, p.getInventory().getContents()); + } + roundStart(); } @@ -111,7 +115,7 @@ public class Game { gameID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> { clearInventories(gamePlayers); giveItems(gamePlayers, new ItemStack(Material.SNOWBALL)); - displayActionbar(gamePlayers, ChatColor.DARK_RED + "Showdown!"); + displayActionbar(gamePlayers, LanguageManager.fromKeyNoPrefix("showdown")); playSound(gamePlayers, Sound.ENTITY_ELDER_GUARDIAN_CURSE, SoundCategory.HOSTILE, 1, 1); // End the round in another 2m30s gameID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, this::roundEnd, 3000); @@ -150,12 +154,12 @@ public class Game { } // 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!", 5, 60, 5); + displayTitles(gamePlayers, LanguageManager.fromKeyNoPrefix("round-over"), LanguageManager.fromKeyNoPrefix("round-winner").replace("%winner%", winner.getDisplayName()), 5, 60, 5); Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, this::roundStart, 100); } } else { - displayTitles(gamePlayers, ChatColor.RED + "Round over!", ChatColor.GOLD + "Draw!", 5, 60, 5); + displayTitles(gamePlayers, LanguageManager.fromKeyNoPrefix("round-over"), LanguageManager.fromKeyNoPrefix("round-draw"), 5, 60, 5); Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, this::roundStart, 100); } } @@ -171,9 +175,9 @@ public class Game { Player winner = getPlayerWithMostWins(gameWins); if (winner != null) { - displayTitles(gamePlayers, ChatColor.RED + "Game over!", ChatColor.GOLD + winner.getName() + " has won the game!", 5, 60, 5); + displayTitles(gamePlayers, LanguageManager.fromKeyNoPrefix("game-over"), LanguageManager.fromKeyNoPrefix("game-winner").replace("%winner%",winner.getDisplayName()), 5, 60, 5); } - displayActionbar(gamePlayers, ChatColor.BLUE + "Returning to lobby in ten seconds..."); + displayActionbar(gamePlayers, LanguageManager.fromKeyNoPrefix("lobby-in-10")); // Wait 10s (200t), then Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> { @@ -186,11 +190,11 @@ public class Game { p.getInventory().setContents(inventories.get(p)); } - if (p == winner && ConfigManager.winnerLobby != null) { - p.teleport(ConfigManager.winnerLobby); + if (p == winner && arena.winnerLobby != null) { + p.teleport(arena.winnerLobby); } else { - p.teleport(Objects.requireNonNull(ConfigManager.lobby)); + p.teleport(Objects.requireNonNull(arena.lobby)); } } @@ -218,7 +222,7 @@ public class Game { if (inventories.containsKey(p)) { p.getInventory().setContents(inventories.get(p)); } - p.teleport(ConfigManager.lobby); + p.teleport(arena.lobby); } /** @@ -229,16 +233,15 @@ public class Game { public void addPlayer(Player p) { gamePlayers.add(p); // save inventory - inventories.put(p, p.getInventory().getContents()); - if (ConfigManager.waitArea != null) { - p.teleport(ConfigManager.waitArea); + if (arena.waitArea != null) { + p.teleport(arena.waitArea); p.getInventory().clear(); } if (gamePlayers.size() >= 2 && gameState == GameState.WAITING) { autoStart(); } else { - displayActionbar(Collections.singletonList(p), ChatColor.YELLOW + "Waiting for players"); + displayActionbar(Collections.singletonList(p), LanguageManager.fromKeyNoPrefix("waiting-for-players")); } } @@ -249,7 +252,7 @@ public class Game { // Wait for the player to load in int waitDuration = ConfigManager.waitDuration; Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> { - displayActionbar(gamePlayers, ChatColor.GREEN + "Game will begin in "+waitDuration+" seconds!"); + displayActionbar(gamePlayers, LanguageManager.fromKeyNoPrefix("time-till-start").replace("%wait%",waitDuration+"")); playSound(gamePlayers, Sound.BLOCK_NOTE_BLOCK_CHIME, SoundCategory.BLOCKS, 1, 1); // Schedule a process to start the game in 300t (15s) and save the PID so we can cancel it later if needed autoStartID = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, this::gameStart, waitDuration * 20L); @@ -280,6 +283,7 @@ public class Game { double x = gameSpawn.getX(); double y = gameSpawn.getY(); double z = gameSpawn.getZ(); + World gameWorld = gameSpawn.getWorld(); // Create the scatter locations based off the game's spawn List<Location> scatterLocations = new ArrayList<>(List.of( new Location(gameWorld, (x - 14.5), y, (z + 0.5), -90, 0), @@ -303,16 +307,16 @@ public class Game { */ private void countdown(Runnable doAfter) { playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 5, 1); - displayTitles(gamePlayers, ChatColor.DARK_GREEN + "3", null, 3, 10, 7); + displayTitles(gamePlayers, LanguageManager.fromKeyNoPrefix("count-3"), null, 3, 10, 7); Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> { playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 5, 1); - displayTitles(gamePlayers, ChatColor.YELLOW + "2", null, 3, 10, 7); + displayTitles(gamePlayers, LanguageManager.fromKeyNoPrefix("count-2"), null, 3, 10, 7); Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> { playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 5, 1); - displayTitles(gamePlayers, ChatColor.DARK_RED + "1", null, 3, 10, 7); + displayTitles(gamePlayers, LanguageManager.fromKeyNoPrefix("count-1"), null, 3, 10, 7); Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> { playSound(gamePlayers, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.NEUTRAL, 5, 2); - displayTitles(gamePlayers, ChatColor.GREEN + "Go!", null, 1, 5, 1); + displayTitles(gamePlayers, LanguageManager.fromKeyNoPrefix("count-go"), null, 1, 5, 1); doAfter.run(); }, 20); }, 20); diff --git a/src/main/java/com/MylesAndMore/Tumble/plugin/ConfigManager.java b/src/main/java/com/MylesAndMore/Tumble/plugin/ConfigManager.java deleted file mode 100644 index c4c1943..0000000 --- a/src/main/java/com/MylesAndMore/Tumble/plugin/ConfigManager.java +++ /dev/null @@ -1,194 +0,0 @@ -package com.MylesAndMore.Tumble.plugin; - -import com.MylesAndMore.Tumble.game.Arena; -import com.MylesAndMore.Tumble.game.Game; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -import java.util.HashMap; -import java.util.Objects; - -import static com.MylesAndMore.Tumble.Main.plugin; - -public class ConfigManager { - public static HashMap<String, Arena> arenas; - public static Location lobby; - public static Location winnerLobby; - public static Location waitArea; - public static boolean HideLeaveJoin; - public static int waitDuration; - - /** - * Reads config file and populates values above - */ - public static void readConfig() { - plugin.reloadConfig(); - FileConfiguration config = plugin.getConfig(); - - HideLeaveJoin = config.getBoolean("hideJoinLeaveMessages", false); - waitDuration = config.getInt("wait-duration", 15); - - // wait area - if (config.getBoolean("wait-area.enable", false)) { - Result<Location>res = readWorld(config.getConfigurationSection("wait-area.spawn")); - if (!res.success) { - plugin.getLogger().warning("Failed to load winner lobby: "+res.error); - waitArea = null; - } - else { - waitArea = res.value; - } - } - - // lobby - { - Result<Location>res = readWorld(config.getConfigurationSection("lobby.spawn")); - if (!res.success) { - plugin.getLogger().warning("Failed to load lobby: "+res.error); - plugin.getLogger().severe("Lobby spawn is required! Lobby spawn will default to spawn in the default world. Run '/tumble-config set lobbyWorld' to change it"); - lobby = Bukkit.getServer().getWorlds().get(0).getSpawnLocation(); - } - else { - lobby = res.value; - } - } - - // winner lobby - if (config.getBoolean("winner-lobby.enable", false)) { - Result<Location>res = readWorld(config.getConfigurationSection("winner-lobby.spawn")); - if (!res.success) { - plugin.getLogger().warning("Failed to load winner lobby: "+res.error); - winnerLobby = null; - } - else { - winnerLobby = res.value; - } - } - - // arenas - ConfigurationSection arenasSection = config.getConfigurationSection("arenas"); - if (arenasSection == null) { - plugin.getLogger().warning("Section 'arenas' is missing from config"); - return; - } - arenas = new HashMap<>(); - for (String arenaName: arenasSection.getKeys(false)) { - - ConfigurationSection anArenaSection = arenasSection.getConfigurationSection(arenaName); - if (anArenaSection == null) { - plugin.getLogger().warning("Failed to load arena "+arenaName+": Error loading config section"); - continue; - } - - Integer killAtY = anArenaSection.getInt("kill-at-y", 0); - if (killAtY == 0) { - killAtY = null; - } - - Result<Location> res = readWorld(anArenaSection.getConfigurationSection("spawn")); - if (!res.success) { - plugin.getLogger().warning("Failed to load arena "+arenaName+": "+res.error); - continue; - } - - arenas.put(arenaName, new Arena(arenaName, res.value, killAtY)); - } - } - - /** - * tries to convert a config section in the following format to a world - * section: - * x: - * y: - * z: - * world: - * @param section the section in the yaml with x, y, z, and world as its children - * @return result of either: - * success = true and a world - * success = false and an error string - */ - private static Result<Location> readWorld(@Nullable ConfigurationSection section) { - - if (section == null) { - return new Result<>("Section missing from config"); - } - - double x = section.getDouble("x"); - double y = section.getDouble("y"); - double z = section.getDouble("z"); - if (x == 0 || y == 0 || z == 0) { - return new Result<>("Arena coordinates are missing or are zero. Coordinates cannot be zero."); - } - - String worldName = section.getString("world"); - if (worldName == null) { - return new Result<>("World name is missing"); - } - - World world = Bukkit.getWorld(worldName); - if (world == null) { - return new Result<>("Failed to load world " + worldName); - } - - return new Result<>(new Location(world,x,y,z)); - } - - public static void WriteConfig() { - if (waitArea != null) { - WriteWorld(Objects.requireNonNull(plugin.getConfig().getConfigurationSection("wait-area")), waitArea); - plugin.getConfig().set("wait-area.enable", true); - } - else { - plugin.getConfig().set("wait-area.enable", false); - } - - if (lobby != null) { - WriteWorld(Objects.requireNonNull(plugin.getConfig().getConfigurationSection("lobby.spawn")), lobby); - } - - if (winnerLobby != null) { - WriteWorld(Objects.requireNonNull(plugin.getConfig().getConfigurationSection("winner-lobby.spawn")), winnerLobby); - plugin.getConfig().set("winner-lobby.enable", true); - } - else { - plugin.getConfig().set("winner-lobby.enable", false); - } - - for (String arenaName: arenas.keySet()) { - ConfigurationSection c = plugin.getConfig().getConfigurationSection("arenas."+arenaName+".spawn"); - if (c == null) { - c = plugin.getConfig().createSection("arenas."+arenaName+".spawn"); - } - WriteWorld(c, arenas.get(arenaName).location); - } - - plugin.saveConfig(); - - } - - private static void WriteWorld(ConfigurationSection section, Location location) { - section.set("x", location.getX()); - section.set("y", location.getY()); - section.set("z", location.getZ()); - section.set("world", Objects.requireNonNull(location.getWorld()).getName()); - } - - /** - * Searches all arenas for a game that player p is in - * @param p Player to search for - * @return the game the player is in, or null if not found - */ - public static Game findGamePlayerIsIn(Player p) { - for (Arena a : arenas.values()) { - if (a.game != null && a.game.gamePlayers.contains(p)) { - return a.game; - } - } - return null; - } -} diff --git a/src/main/java/com/MylesAndMore/Tumble/plugin/SubCommand.java b/src/main/java/com/MylesAndMore/Tumble/plugin/SubCommand.java new file mode 100644 index 0000000..2158584 --- /dev/null +++ b/src/main/java/com/MylesAndMore/Tumble/plugin/SubCommand.java @@ -0,0 +1,8 @@ +package com.MylesAndMore.Tumble.plugin; + +import org.bukkit.command.CommandExecutor; + +public interface SubCommand extends CommandExecutor { + public String getCommandName(); + public String getPermission(); +} diff --git a/src/main/resources/arenas.yml b/src/main/resources/arenas.yml new file mode 100644 index 0000000..7b902be --- /dev/null +++ b/src/main/resources/arenas.yml @@ -0,0 +1,23 @@ +arenas: + 'test': + kill-at-y: 5 + game-spawn: + x: 100 + y: 100 + z: 100 + world: world + lobby: + x: 0.5 + y: 100 + z: 0.5 + world: world + winner-lobby: + x: 0.5 + y: 100 + z: 0.5 + world: world + wait-arena: + x: 0.5 + y: 100 + z: 0.5 + world: world
\ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index b13570e..97f0a12 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -3,42 +3,5 @@ hideJoinLeaveMessages: false # Duration in seconds to wait for more players to join wait-duration: 15 -# Teleport players somewhere while waiting for the game to start -# Keep in mind that these coordinates cannot be zero! Use something like 0.5 instead -wait-area: - enable: false - spawn: - x: - y: - z: - world: -# Place where everyone is teleported to after a game ends REQUIRED -# Keep in mind that these coordinates cannot be zero! Use something like 0.5 instead -lobby: - spawn: - x: 0.5 - y: 100 - z: 0.5 - world: world -# Place that the winner is teleported after a game ends -# Keep in mind that these coordinates cannot be zero! Use something like 0.5 instead -winner-lobby: - enable: false - spawn: - x: - y: - z: - world: - -# Add/remove as you wish -# Keep in mind that these coordinates cannot be zero! Use something like 0.5 instead -arenas: - 'test': - kill-at-y: 5 - spawn: - x: 100 - y: 100 - z: 100 - world: world
\ No newline at end of file diff --git a/src/main/resources/language.yml b/src/main/resources/language.yml new file mode 100644 index 0000000..fa57b1c --- /dev/null +++ b/src/main/resources/language.yml @@ -0,0 +1,42 @@ +prefix: "&f[&eTumble&f] " + +unknown-command: "&4Unknown command '%command%'" +no-permission: "&4You do not have permission to perform this command! &7Required permission: '%permission%.'" +missing-arena-parameter: "&4Missing arena name!" +invalid-arena: "&4arena '%arena%' does not exist!" +invalid-type: "&4Invalid game type" +no-game-in-arena: "&4No game is currently running in this arena" +player-not-in-game: "&4You are not in a game!" +not-for-console: "&4This cannot be run by the console" +game-in-progress: "&4This game is still in progress!&7 wait until it finishes or join another game" +another-type-in-arena: "A game of %type% is currently taking place in this arena!&7 choose another arena or join it with &a/tmbl join %arena% %type%" +already-in-game: "&4You are already in a game! Leave it to join another one." + +create-success: "&aArena created successfully! &eBefore you can join, you must set a game spawn location with /tmbl setGameSpawn" +forcestart-success: "&aStarting game." +forcestop-success: "&aGame stopped." +join-success: "&aJoined game &d%arena% - %type%" +leave-success: "&aLeft game &d%arena% - %type%" +reload-success: "&aConfiguration reloaded. &eCheck console for errors." +remove-success: "&aArena removed." +set-success: "&aLocation set." + +showdown: "&4Showdown!" +lobby-in-10: "&9Returning to lobby in ten seconds..." +waiting-for-players: "&aWaiting for players" +time-till-start: "&aGame will begin in %wait% seconds!" +round-over: "&cRound over!" +round-winner: "&6%winner% has won the round!" +round-draw: "&6Draw!" +game-over: "&Game over!" +game-winner: "&6%winner% has won the Game!" +count-3: "&23" +count-2: "&e2" +count-1: "&41" +count-go: "&aGo!" + + + + + + diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 486fccf..ed246c5 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -7,31 +7,14 @@ load: POSTWORLD author: MylesAndMore website: https://github.com/MylesAndMore/Tumble softdepend: [Multiverse-Core] + commands: - tumble-join: + tumble: description: Joins a Tumble match. - usage: '§cUsage: /tumble-join <arenaName> [gameType]' + usage: '§cUsage: /tumble' permission: tumble.join - tumble-leave: - description: Quits a Tumble match. - usage: '§cUsage: /tumble-leave' - permission: tumble.leave - tumble-forcestart: - description: Force starts a Tumble match. - usage: '§cUsage: /tumble-forcestart [arenaName]' - permission: tumble.forcestart - tumble-forcestop: - description: Force stops a Tumble match. - usage: '§cUsage: /tumble-forcestop [arenaName]' - permission: tumble.forcestop - tumble-config: - description: Modify arenas and worlds. - usage: '§cUsage: /tumble-config <add|set|disable|delete> <data>' - permission: tumble.config - tumble-reload: - description: Reloads the plugin's config. - usage: '§cUsage: /tumble-reload' - permission: tumble.reload + aliases: tmbl + permissions: tumble.join: description: Allows you to join a Tumble match. |