diff --git a/pom.xml b/pom.xml index 0ce1bf7..7022d61 100644 --- a/pom.xml +++ b/pom.xml @@ -67,11 +67,20 @@ + ${project.build.directory}/dependency-reduced-pom.xml xyz.twovb.toolbox ${project.groupId}.${project.artifactId}.toolbox + + com.github.stefvanschie.inventoryframework + ${project.groupId}.${project.artifactId}.inventoryframework + + + net.megavex.scoreboardlibrary + ${project.groupId}.${project.artifactId}.scoreboardlibrary + @@ -159,7 +168,30 @@ commons-io 2.16.1 - + + com.github.stefvanschie.inventoryframework + IF + 0.10.15 + + + net.megavex + scoreboard-library-api + 2.1.10 + + + net.megavex + scoreboard-library-implementation + 2.1.10 + runtime + + + net.megavex + scoreboard-library-modern + 2.1.10 + runtime + + + diff --git a/src/main/java/xyz/twovb/sgm/SGM.java b/src/main/java/xyz/twovb/sgm/SGM.java index c07d7d6..efa2116 100644 --- a/src/main/java/xyz/twovb/sgm/SGM.java +++ b/src/main/java/xyz/twovb/sgm/SGM.java @@ -1,8 +1,17 @@ package xyz.twovb.sgm; + +/* + * Created by 2vb - 5/7/2024 + */ + import dev.rollczi.litecommands.bukkit.LiteBukkitMessages; import dev.rollczi.litecommands.bukkit.LiteCommandsBukkit; import lombok.Getter; +import net.megavex.scoreboardlibrary.api.ScoreboardLibrary; +import net.megavex.scoreboardlibrary.api.exception.NoPacketAdapterAvailableException; +import net.megavex.scoreboardlibrary.api.noop.NoopScoreboardLibrary; +import net.megavex.scoreboardlibrary.api.team.TeamManager; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; @@ -40,6 +49,10 @@ public final class SGM extends JavaPlugin { @Getter private LevelManager levelManager; + @Getter + private ScoreboardLibrary scoreboardLibrary; + @Getter + private TeamManager teamManager; @Override public void onEnable() { @@ -55,12 +68,32 @@ public final class SGM extends JavaPlugin { BuildInfo.load(Objects.requireNonNull(this.getTextResource("build-info.yml"))); } catch (IOException | InvalidConfigurationException ignored) { } + loadScoreboard(); + loadGuis(); registerCommands(); registerGames(); registerPlaceholders(); levelManager.loadLevels(); } + private void loadScoreboard() { + try { + scoreboardLibrary = ScoreboardLibrary.loadScoreboardLibrary(this); + } catch (NoPacketAdapterAvailableException e) { + // If no packet adapter was found, you can fallback to the no-op implementation: + scoreboardLibrary = new NoopScoreboardLibrary(); + this.getCLogger().error("No scoreboard packet adapter found."); + } + } + + private void loadGuis() { + saveResource("guis/initgame.xml", false); + saveResource("guis/mapgui.xml", false); + saveResource("guis/teampicker.xml", false); + saveResource("guis/activegames.xml", false); + saveResource("guis/joingame.xml", false); + } + private void registerPlaceholders() { PlaceholderManager pm = new PlaceholderManager(); pm.registerPlaceholder("%commit.id%", BuildInfo.getString("commit.id")); diff --git a/src/main/java/xyz/twovb/sgm/commands/impl/GameCommand.java b/src/main/java/xyz/twovb/sgm/commands/impl/GameCommand.java index d9a9b60..d303336 100644 --- a/src/main/java/xyz/twovb/sgm/commands/impl/GameCommand.java +++ b/src/main/java/xyz/twovb/sgm/commands/impl/GameCommand.java @@ -1,5 +1,16 @@ package xyz.twovb.sgm.commands.impl; + + +/* + * Created by 2vb - 5/7/2024 + */ + + +/* + * Created by 2vb - 5/7/2024 + */ + /* * Created by 2vb - 2/7/2024 */ @@ -13,11 +24,13 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import xyz.twovb.sgm.SGM; import xyz.twovb.sgm.games.Minigame; -import xyz.twovb.sgm.games.impl.TestGame; -import xyz.twovb.sgm.games.impl.capturethebrick.CTB; +import xyz.twovb.sgm.games.impl.capturethebrick.guis.TeamGui; +import xyz.twovb.sgm.guis.InitGameGui; +import xyz.twovb.sgm.guis.JoinGameGui; import xyz.twovb.toolbox.api.CustomPlayer; import xyz.twovb.toolbox.utils.ChatUtils; +import java.util.Optional; import java.util.UUID; @Command(name = "game") @@ -40,9 +53,10 @@ public class GameCommand { @Execute(name = "init") @Permission("sgm.games.init") - void init(@Context Player player, @Arg("name") String name) { + void init(@Context Player player, @Arg("name") Optional map) { CustomPlayer cPlayer = new CustomPlayer(player); - SGM.getInstance().getGameManager().initGame(new CTB(), player, name); + new InitGameGui().getGui().show(player); +// SGM.getInstance().getGameManager().initGame(new CTB(), player, name); } @Execute(name = "start") @@ -53,6 +67,19 @@ public class GameCommand { game.start(); } + @Execute(name = "team join") + @Permission("sgm.games.team") + void teamJoin(@Context Player player, @Arg("player") Optional target) { +// String name = LevelName.orElse(UUID.randomUUID().toString()); + Player targetPlayer = target.orElse(player); + new TeamGui(targetPlayer).getGui().show(player); + } + + @Execute(name = "testjoin") + void testjoin(@Context Player player) { + new JoinGameGui().getGui().show(player); + } + @Execute(name = "join") void join(@Context Player player, @Arg("id") String id) { CustomPlayer cPlayer = new CustomPlayer(player); diff --git a/src/main/java/xyz/twovb/sgm/games/GameManager.java b/src/main/java/xyz/twovb/sgm/games/GameManager.java index e5643b8..f68771c 100644 --- a/src/main/java/xyz/twovb/sgm/games/GameManager.java +++ b/src/main/java/xyz/twovb/sgm/games/GameManager.java @@ -1,5 +1,10 @@ package xyz.twovb.sgm.games; + +/* + * Created by 2vb - 5/7/2024 + */ + /* * Created by 2vb - 4/6/2024 */ @@ -11,8 +16,8 @@ import xyz.twovb.sgm.SGM; import xyz.twovb.toolbox.managers.PlaceholderManager; import xyz.twovb.toolbox.utils.ChatUtils; -import java.io.File; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -25,19 +30,12 @@ public class GameManager { @Getter private final ArrayList registeredGames = new ArrayList(); + private final Map> gameMappings = new HashMap<>(); + public static Minigame findGame(UUID gameId) { return activeGames.get(gameId); } - public Minigame findGame(Player player) { - for (Minigame game : activeGames.values()) { - if (game.getPlayers().contains(player)) { - return game; - } - } - return null; - } - public static boolean isInGame(Player player) { for (Minigame game : activeGames.values()) { if (game.getPlayers().contains(player)) { @@ -47,16 +45,37 @@ public class GameManager { return false; } - public void initGame(Minigame game, CommandSender owner, String level) { + public Minigame findGame(Player player) { + for (Minigame game : activeGames.values()) { + if (game.getPlayers().contains(player)) { + return game; + } + } + return null; + } + + public void initGame(String internalName, CommandSender owner, String level) { try { + Minigame game = createGameInstance(internalName); game.init(owner, level); - } catch (IOException e) { + activeGames.put(game.getGameId(), game); + } catch (InstantiationException | IllegalAccessException | IOException | NoSuchMethodException | + InvocationTargetException e) { SGM.getInstance().getCLogger().error(e.getMessage()); owner.sendMessage(ChatUtils.translate(PlaceholderManager.setPlaceholders(SGM.getInstance().getMessages().getString("sgm.game.cant-start"), owner))); } - activeGames.put(game.getGameId(), game); } +// public void initGame(Minigame game, CommandSender owner, String level) { +// try { +// game.init(owner, level); +// } catch (IOException e) { +// SGM.getInstance().getCLogger().error(e.getMessage()); +// owner.sendMessage(ChatUtils.translate(PlaceholderManager.setPlaceholders(SGM.getInstance().getMessages().getString("sgm.game.cant-start"), owner))); +// } +// activeGames.put(game.getGameId(), game); +// } + public void addPlayerToGame(Player player, UUID gameId) { Minigame game = findGame(gameId); if (game.getState() == Minigame.GameState.READY && !game.getPlayers().contains(player) && !isInGame(player)) { @@ -69,17 +88,28 @@ public class GameManager { game.removePlayer(player); } + public Minigame createGameInstance(String internalName) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { + Class gameClass = gameMappings.get(internalName); + if (gameClass != null) { + return gameClass.getDeclaredConstructor().newInstance(); + } else { + throw new IllegalArgumentException("No game registered with internal name: " + internalName); + } + } + public void registerGame(Minigame game) { String intName = game.getName().toLowerCase(); try { SGM.getInstance().getConfigManager().loadConfig("games/" + intName + "/options.yml"); registeredGames.add(intName); + gameMappings.put(intName, game.getClass()); SGM.getInstance().getCLogger().log("Registered game " + game.getName()); - } catch(IllegalArgumentException error) { + } catch (IllegalArgumentException error) { String errMsg = error.getMessage(); if (errMsg.contains("The embedded resource") && errMsg.contains("cannot be found")) { SGM.getInstance().getCLogger().log(game.getName() + "'s game options are nowhere to be found. Please ensure this is intended behaviour."); registeredGames.add(intName); + gameMappings.put(intName, game.getClass()); } else { SGM.getInstance().getCLogger().error("Failed to register game " + game.getName() + ". Reason: " + errMsg); } diff --git a/src/main/java/xyz/twovb/sgm/games/Minigame.java b/src/main/java/xyz/twovb/sgm/games/Minigame.java index 3359636..a03b945 100644 --- a/src/main/java/xyz/twovb/sgm/games/Minigame.java +++ b/src/main/java/xyz/twovb/sgm/games/Minigame.java @@ -1,5 +1,10 @@ package xyz.twovb.sgm.games; + +/* + * Created by 2vb - 5/7/2024 + */ + /* * Created by 2vb - 4/6/2024 */ @@ -9,7 +14,6 @@ import org.bukkit.NamespacedKey; import org.bukkit.World; import org.bukkit.WorldCreator; import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.Listener; import xyz.twovb.sgm.SGM; @@ -43,6 +47,8 @@ public interface Minigame extends Listener { GameState getState(); + World getWorld(); + default void sendMessageToAllPlayers(String message) { for (Player player : getPlayers()) { CustomPlayer cPlayer = new CustomPlayer(player); diff --git a/src/main/java/xyz/twovb/sgm/games/impl/TestGame.java b/src/main/java/xyz/twovb/sgm/games/impl/TestGame.java index b1f47bf..235f062 100644 --- a/src/main/java/xyz/twovb/sgm/games/impl/TestGame.java +++ b/src/main/java/xyz/twovb/sgm/games/impl/TestGame.java @@ -1,5 +1,10 @@ package xyz.twovb.sgm.games.impl; + +/* + * Created by 2vb - 5/7/2024 + */ + /* * Created by 2vb - 26/6/2024 */ @@ -117,6 +122,12 @@ public class TestGame implements Minigame { return state; } + + @Override + public World getWorld() { + return gameWorld; + } + @Override public void onTick() { if (state == GameState.STARTED && players.size() <= 1) { diff --git a/src/main/java/xyz/twovb/sgm/games/impl/capturethebrick/CTB.java b/src/main/java/xyz/twovb/sgm/games/impl/capturethebrick/CTB.java index cf4db34..35013ff 100644 --- a/src/main/java/xyz/twovb/sgm/games/impl/capturethebrick/CTB.java +++ b/src/main/java/xyz/twovb/sgm/games/impl/capturethebrick/CTB.java @@ -1,9 +1,31 @@ package xyz.twovb.sgm.games.impl.capturethebrick; + + /* - * Created by 2vb - 3/7/2024 + * Created by 2vb - 5/7/2024 */ + +/* + * Created by 2vb - 5/7/2024 + */ + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.format.TextDecoration; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.megavex.scoreboardlibrary.api.sidebar.Sidebar; +import net.megavex.scoreboardlibrary.api.sidebar.component.ComponentSidebarLayout; +import net.megavex.scoreboardlibrary.api.sidebar.component.SidebarComponent; +import net.megavex.scoreboardlibrary.api.sidebar.component.animation.CollectionSidebarAnimation; +import net.megavex.scoreboardlibrary.api.sidebar.component.animation.SidebarAnimation; +import net.megavex.scoreboardlibrary.api.team.ScoreboardTeam; +import net.megavex.scoreboardlibrary.api.team.TeamDisplay; +import net.megavex.scoreboardlibrary.api.team.TeamManager; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -11,16 +33,21 @@ import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.command.CommandSender; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerChangedWorldEvent; import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; import xyz.twovb.sgm.SGM; import xyz.twovb.sgm.games.GameManager; import xyz.twovb.sgm.games.Minigame; import xyz.twovb.sgm.levels.LevelManager; +import xyz.twovb.toolbox.utils.ChatUtils; import java.io.File; import java.io.IOException; @@ -35,18 +62,33 @@ public class CTB implements Minigame { private final ArrayList blueBrickSpawns = new ArrayList(); private final ArrayList redSpawnArea = new ArrayList(); private final ArrayList blueSpawnArea = new ArrayList(); + private final FileConfiguration messages; private World gameWorld; private GameState state; private int bricks; private int territoryLevel; private int boundsLevel; private Location spawnLoc; + private TeamManager teamManager; + private ScoreboardTeam redTeam; + private ScoreboardTeam blueTeam; + private Sidebar sb; + private SidebarAnimation titleAnimation; + // private @NotNull SidebarComponent title; + private ComponentSidebarLayout layout; + + private int taskId; + +// private List redTeam = new ArrayList(); +// private List blueTeam = new ArrayList(); +// private Sidebar sb; public CTB() { this.uuid = UUID.randomUUID(); this.state = GameState.PRESTART; this.players = new ArrayList<>(); + this.messages = SGM.getInstance().getConfigManager().loadConfig("games/" + name.toLowerCase() + "/messages.yml"); } public void init(CommandSender owner, String world) throws IOException { @@ -54,14 +96,65 @@ public class CTB implements Minigame { gameWorld = createGameWorld(world, uuid); gameWorld.setAutoSave(false); if (applyOptions(world)) { + teamManager = SGM.getInstance().getScoreboardLibrary().createTeamManager(); + this.redTeam = teamManager.createIfAbsent("red_team"); + this.blueTeam = teamManager.createIfAbsent("blue_team"); Bukkit.getPluginManager().registerEvents(this, SGM.getInstance()); + + setupTeamDisplay(redTeam, "Red Team", NamedTextColor.RED); + setupTeamDisplay(blueTeam, "Blue Team", NamedTextColor.BLUE); + + this.sb = SGM.getInstance().getScoreboardLibrary().createSidebar(); + this.titleAnimation = createGradientAnimation(Component.text("Capture The Brick", Style.style(TextDecoration.BOLD))); + var title = SidebarComponent.animatedLine(titleAnimation); + + SidebarComponent gameInfo = SidebarComponent.builder().addDynamicLine(() -> Component.text("Players Alive: " + getAlivePlayersCount(), NamedTextColor.YELLOW)).addDynamicLine(() -> Component.text("Red Team: " + getTeamSize(redTeam), NamedTextColor.RED)).addDynamicLine(() -> Component.text("Blue Team: " + getTeamSize(blueTeam), NamedTextColor.BLUE)).addDynamicLine(() -> Component.text("Bricks Remaining: " + bricks, NamedTextColor.GREEN)).build(); + + this.layout = new ComponentSidebarLayout(title, gameInfo); + layout.apply(sb); + +// buildScoreboard(); + // Ready state = GameState.READY; - owner.sendMessage("A new " + name + " instance with ID " + uuid + " has been created and is now ready!"); + owner.sendMessage(ChatUtils.translate(messages.getString("system.game.ready").replace("%game%", name))); } else { - owner.sendMessage("a"); -// owner.sendMessage(ChatUtils.translate(SGM.getInstance().getMessages().getString("sgm.game.cant-start"))); + owner.sendMessage(ChatUtils.translate(messages.getString("system.game.failed").replace("%cause%", "to load options."))); + this.stop(); + } + } + + private void setupTeamDisplay(ScoreboardTeam team, String displayName, NamedTextColor color) { + TeamDisplay display = team.defaultDisplay(); + display.displayName(Component.text(displayName)); + display.playerColor(color); + } + +// private void buildScoreboard() { +// titleAnimation = createGradientAnimation(Component.text("Capture The Brick", Style.style(TextDecoration.BOLD))); +// title = SidebarComponent.animatedLine(titleAnimation); +// SidebarComponent lines = SidebarComponent.builder().addDynamicLine(() -> Component.text("Red Team: " + redTeam.teamManager().players().size(), NamedTextColor.RED)).addDynamicLine(() -> Component.text("Blue Team: " + blueTeam.teamManager().players().size(), NamedTextColor.BLUE)).addDynamicLine(() -> Component.text("Bricks Remaining: " + bricks, NamedTextColor.GREEN)).build(); +// layout = new ComponentSidebarLayout(title, lines); +// layout.apply(sb); +// } + + private @NotNull SidebarAnimation createGradientAnimation(@NotNull Component text) { + float step = 1f / 8f; + TagResolver.Single textPlaceholder = Placeholder.component("text", text); + List frames = new ArrayList<>((int) (2f / step)); + float phase = -1f; + + SGM.getInstance().getCLogger().log("Creating gradient animation"); + + while (phase <= 1) { + String gradientTag = String.format("", phase); + Component frame = MiniMessage.miniMessage().deserialize(gradientTag + "", textPlaceholder); + frames.add(frame); + SGM.getInstance().getCLogger().log("Phase: " + phase + ", Tag: " + gradientTag); + phase += step; } + SGM.getInstance().getCLogger().log("Total frames: " + frames.size()); + return new CollectionSidebarAnimation<>(frames); } private Location parseString(String string) { @@ -146,8 +239,9 @@ public class CTB implements Minigame { sendMessageToAllPlayers("The game has started!"); for (Player player : players) { player.teleport(this.spawnLoc); + sb.addPlayer(player); } - for (int i = 0; i < bricks; i++) { + for (int i = 0; i <= bricks; i++) { for (Location brickLoc : redBrickSpawns) { placeBrick(brickLoc, "red"); } @@ -155,10 +249,35 @@ public class CTB implements Minigame { placeBrick(brickLoc, "blue"); } } - Bukkit.getScheduler().runTaskTimer(SGM.getInstance(), this::onTick, 0L, 1L); + BukkitTask task = Bukkit.getScheduler().runTaskTimer(SGM.getInstance(), this::onTick, 0L, 1L); + this.taskId = task.getTaskId(); } } + public void addPlayerToTeam(Player player, boolean isRedTeam) { + //TODO: make this shit fuckin better bor + if (isRedTeam) { + redTeam.defaultDisplay().addEntry(player.getName()); + } else { + blueTeam.defaultDisplay().addEntry(player.getName()); + } + teamManager.addPlayer(player); + } + + public void removePlayerFromTeams(Player player) { + redTeam.defaultDisplay().removeEntry(player.getName()); + blueTeam.defaultDisplay().removeEntry(player.getName()); + teamManager.removePlayer(player); + } + + public int getAlivePlayersCount() { + return (int) players.stream().filter(Player::isOnline).count(); + } + + public int getTeamSize(ScoreboardTeam team) { + return team.defaultDisplay().entries().size(); + } + private void placeBrick(Location location, String team) { Block brick = location.getBlock(); if (Objects.equals(team, "red")) { @@ -172,6 +291,7 @@ public class CTB implements Minigame { @Override public void stop() { + // TODO: make it wait before unloading world // Stop game logic state = GameState.ENDING; Player winner; @@ -186,18 +306,28 @@ public class CTB implements Minigame { player.teleport(Bukkit.getServer().getWorlds().get(0).getSpawnLocation()); } Bukkit.unloadWorld(gameWorld, false); + if (teamManager != null) { + teamManager.close(); + } + if (sb != null) { + sb.close(); + } + Bukkit.getScheduler().cancelTask(this.taskId); } @Override public void addPlayer(Player player) { players.add(player); +// sb.addPlayer(player); player.teleport(this.spawnLoc); - sendMessageToAllPlayers(player.getName() + " has joined the game!"); + sendMessageToAllPlayers(messages.getString("system.player.join").replace("%player%", player.getName())); } @Override public void removePlayer(Player player) { players.remove(player); + sb.removePlayer(player); + sendMessageToAllPlayers(messages.getString("system.player.left").replace("%player%", player.getName())); } @EventHandler @@ -208,6 +338,14 @@ public class CTB implements Minigame { } } + @EventHandler + void onWorldChange(PlayerChangedWorldEvent event) { + Player player = event.getPlayer(); + if (players.contains(player)) { + removePlayer(event.getPlayer()); + } + } + @EventHandler void onPlayerDeath(PlayerDeathEvent event) { Player player = event.getPlayer(); @@ -238,21 +376,26 @@ public class CTB implements Minigame { return state; } -// @EventHandler -// void onPlayerMove(PlayerMoveEvent event) { -// Player player = event.getPlayer(); -// CustomPlayer cPlayer = new CustomPlayer(player); -// cPlayer.sendMessage("move"); -// if (event.getFrom().getX() != event.getTo().getX() || event.getFrom().getZ() != event.getTo().getZ()) { -// cPlayer.sendMessage("move full block"); -// } -// } + @Override + public World getWorld() { + return gameWorld; + } @Override public void onTick() { + for (Player player : gameWorld.getPlayers()) { + if (!players.contains(player)) { + sendMessageToAllPlayers(player.getName() + " IS A IMPOSTER"); + } + } if (state == GameState.STARTED && players.size() <= 1) { this.stop(); } + try { + titleAnimation.nextFrame(); + layout.apply(sb); + } catch (IllegalStateException ignored) { + } } } \ No newline at end of file diff --git a/src/main/java/xyz/twovb/sgm/games/impl/capturethebrick/guis/TeamGui.java b/src/main/java/xyz/twovb/sgm/games/impl/capturethebrick/guis/TeamGui.java new file mode 100644 index 0000000..faedbc7 --- /dev/null +++ b/src/main/java/xyz/twovb/sgm/games/impl/capturethebrick/guis/TeamGui.java @@ -0,0 +1,63 @@ +package xyz.twovb.sgm.games.impl.capturethebrick.guis; + + +/* + * Created by 2vb - 5/7/2024 + */ + +import com.github.stefvanschie.inventoryframework.gui.type.ChestGui; +import lombok.Getter; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import xyz.twovb.sgm.SGM; +import xyz.twovb.sgm.games.impl.capturethebrick.CTB; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.logging.Level; + +public class TeamGui { + @Getter + private final ChestGui gui; + + private Player target; + + public TeamGui(Player player) { + ChestGui loadedGui = null; + try { + File guiFile = new File(SGM.getInstance().getDataFolder(), "guis/teampicker.xml"); + if (guiFile.exists()) { + byte[] fileContent = Files.readAllBytes(guiFile.toPath()); + InputStream inputStream = new ByteArrayInputStream(fileContent); + loadedGui = ChestGui.load(this, inputStream); + } else { + SGM.getInstance().getLogger().log(Level.WARNING, "Could not find teampicker.xml file."); + } + } catch (Exception e) { + SGM.getInstance().getLogger().log(Level.SEVERE, "Error loading teampicker.xml", e); + } + gui = loadedGui; + target = player; + } + + public void globalClick(InventoryClickEvent event) { + event.setCancelled(true); + } + + public void pickTeam(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + ItemStack clickedItem = event.getCurrentItem(); + CTB game = (CTB) SGM.getInstance().getGameManager().findGame(player); + if (clickedItem.getType().equals(Material.RED_WOOL)) { + game.addPlayerToTeam(target, true); + game.sendMessageToAllPlayers(target.getName() + " RED"); + } else if (clickedItem.getType().equals(Material.BLUE_WOOL)) { + game.addPlayerToTeam(target, false); + game.sendMessageToAllPlayers(target.getName() + " BLUE"); + } + } +} diff --git a/src/main/java/xyz/twovb/sgm/guis/ActiveGamesGui.java b/src/main/java/xyz/twovb/sgm/guis/ActiveGamesGui.java new file mode 100644 index 0000000..55d4502 --- /dev/null +++ b/src/main/java/xyz/twovb/sgm/guis/ActiveGamesGui.java @@ -0,0 +1,110 @@ +package xyz.twovb.sgm.guis; + +/* + * Created by 2vb - 5/7/2024 + */ + +/* + * Created by 2vb - 5/7/2024 + */ + +import com.github.stefvanschie.inventoryframework.gui.GuiItem; +import com.github.stefvanschie.inventoryframework.gui.type.ChestGui; +import com.github.stefvanschie.inventoryframework.pane.OutlinePane; +import lombok.Getter; +import net.kyori.adventure.text.Component; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import xyz.twovb.sgm.SGM; +import xyz.twovb.sgm.games.GameManager; +import xyz.twovb.sgm.games.Minigame; +import xyz.twovb.toolbox.utils.ChatUtils; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; + +public class ActiveGamesGui { + + @Getter + private final ChestGui gui; + + private final String game; + private OutlinePane mapPane; + + public ActiveGamesGui(String game) { + this.game = game; + ChestGui loadedGui = null; + try { + File guiFile = new File(SGM.getInstance().getDataFolder(), "guis/activegames.xml"); + if (guiFile.exists()) { + byte[] fileContent = Files.readAllBytes(guiFile.toPath()); + InputStream inputStream = new ByteArrayInputStream(fileContent); + loadedGui = ChestGui.load(this, inputStream); + mapPane = new OutlinePane(1, 1, 7, 1); // Define your pane layout + loadedGui.addPane(mapPane); + addMaps(); + } else { + SGM.getInstance().getLogger().log(Level.WARNING, "Could not find activegames.xml file."); + } + } catch (Exception e) { + SGM.getInstance().getLogger().log(Level.SEVERE, "Error loading activegames.xml", e); + } + gui = loadedGui; + } + + public void globalClick(InventoryClickEvent event) { + event.setCancelled(true); + } + + public void addMaps() { + for (Minigame game : GameManager.getActiveGames().values()) { +// SGM.getInstance().getCLogger().log(game.getName()); +// SGM.getInstance().getCLogger().log(this.game); + Material itemType; + switch (game.getState()) { + case PRESTART: +// mapItem.setType(Material.YELLOW_WOOL); + itemType = Material.YELLOW_WOOL; + break; + case READY: +// mapItem.setType(Material.LIME_WOOL); + itemType = Material.LIME_WOOL; + break; + case STARTED: + case ENDING: + default: +// mapItem.setType(Material.RED_WOOL); + itemType = Material.RED_WOOL; + break; + } + ItemStack joinItem = new ItemStack(itemType); + ItemMeta meta = joinItem.getItemMeta(); + meta.displayName(ChatUtils.translate(game.getName())); + List lore = new ArrayList(); + lore.add(0, ChatUtils.translate("&r&7" + game.getGameId().toString())); + if (!game.getPlayers().isEmpty()) { + lore.add(ChatUtils.translate("&r&7Players:")); + for (Player player : game.getPlayers()) { + lore.add(ChatUtils.translate("&r&a" + player.getName())); + } + } + meta.lore(lore); + joinItem.setItemMeta(meta); + mapPane.addItem(new GuiItem(joinItem, event -> { + Player player = (Player) event.getWhoClicked(); + if (game.getState() == Minigame.GameState.READY) { + SGM.getInstance().getGameManager().addPlayerToGame(player, game.getGameId()); + } + player.closeInventory(); + })); + } + } +} diff --git a/src/main/java/xyz/twovb/sgm/guis/InitGameGui.java b/src/main/java/xyz/twovb/sgm/guis/InitGameGui.java new file mode 100644 index 0000000..460389e --- /dev/null +++ b/src/main/java/xyz/twovb/sgm/guis/InitGameGui.java @@ -0,0 +1,55 @@ +package xyz.twovb.sgm.guis; +/* + * Created by 2vb - 4/7/2024 + */ + +import com.github.stefvanschie.inventoryframework.gui.type.ChestGui; +import lombok.Getter; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import xyz.twovb.sgm.SGM; +import xyz.twovb.sgm.games.impl.capturethebrick.CTB; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.logging.Level; + +public class InitGameGui { + + @Getter + private final ChestGui gui; + + public InitGameGui() { + ChestGui loadedGui = null; + try { + File guiFile = new File(SGM.getInstance().getDataFolder(), "guis/initgame.xml"); + if (guiFile.exists()) { + byte[] fileContent = Files.readAllBytes(guiFile.toPath()); + InputStream inputStream = new ByteArrayInputStream(fileContent); + loadedGui = ChestGui.load(this, inputStream); + } else { + SGM.getInstance().getLogger().log(Level.WARNING, "Could not find initgame.xml file."); + } + } catch (Exception e) { + SGM.getInstance().getLogger().log(Level.SEVERE, "Error loading initgame.xml", e); + } + gui = loadedGui; + } + + public void globalClick(InventoryClickEvent event) { + event.setCancelled(true); + } + + public void initGame(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + String itemName = event.getCurrentItem().getItemMeta().getDisplayName().replaceAll("\\W+", ""); + player.closeInventory(); + if (SGM.getInstance().getGameManager().getRegisteredGames().contains(itemName.toLowerCase())) { + new MapGui(itemName.toLowerCase()).getGui().show(player); + } else { + player.sendMessage("Please check xml"); + } + } +} diff --git a/src/main/java/xyz/twovb/sgm/guis/JoinGameGui.java b/src/main/java/xyz/twovb/sgm/guis/JoinGameGui.java new file mode 100644 index 0000000..1a5ef6b --- /dev/null +++ b/src/main/java/xyz/twovb/sgm/guis/JoinGameGui.java @@ -0,0 +1,59 @@ +package xyz.twovb.sgm.guis; + +/* + * Created by 2vb - 5/7/2024 + */ + +/* + * Created by 2vb - 5/7/2024 + */ + +import com.github.stefvanschie.inventoryframework.gui.type.ChestGui; +import lombok.Getter; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import xyz.twovb.sgm.SGM; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.logging.Level; + +public class JoinGameGui { + + @Getter + private final ChestGui gui; + + public JoinGameGui() { + ChestGui loadedGui = null; + try { + File guiFile = new File(SGM.getInstance().getDataFolder(), "guis/joingame.xml"); + if (guiFile.exists()) { + byte[] fileContent = Files.readAllBytes(guiFile.toPath()); + InputStream inputStream = new ByteArrayInputStream(fileContent); + loadedGui = ChestGui.load(this, inputStream); + } else { + SGM.getInstance().getLogger().log(Level.WARNING, "Could not find joingame.xml file."); + } + } catch (Exception e) { + SGM.getInstance().getLogger().log(Level.SEVERE, "Error loading joingame.xml", e); + } + gui = loadedGui; + } + + public void globalClick(InventoryClickEvent event) { + event.setCancelled(true); + } + + public void joinGame(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + String itemName = event.getCurrentItem().getItemMeta().getDisplayName().replaceAll("\\W+", ""); + player.closeInventory(); + if (SGM.getInstance().getGameManager().getRegisteredGames().contains(itemName.toLowerCase())) { + new ActiveGamesGui(itemName).getGui().show(player); + } else { + player.sendMessage("Please check xml"); + } + } +} diff --git a/src/main/java/xyz/twovb/sgm/guis/MapGui.java b/src/main/java/xyz/twovb/sgm/guis/MapGui.java new file mode 100644 index 0000000..ca58d86 --- /dev/null +++ b/src/main/java/xyz/twovb/sgm/guis/MapGui.java @@ -0,0 +1,82 @@ +package xyz.twovb.sgm.guis; + + +/* + * Created by 2vb - 5/7/2024 + */ + +import com.github.stefvanschie.inventoryframework.gui.GuiItem; +import com.github.stefvanschie.inventoryframework.gui.type.ChestGui; +import com.github.stefvanschie.inventoryframework.pane.OutlinePane; +import lombok.Getter; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import xyz.twovb.sgm.SGM; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.List; +import java.util.logging.Level; + +public class MapGui { + + @Getter + private final ChestGui gui; + + private final String game; + private OutlinePane mapPane; + + public MapGui(String game) { + this.game = game; + ChestGui loadedGui = null; + try { + File guiFile = new File(SGM.getInstance().getDataFolder(), "guis/mapgui.xml"); + if (guiFile.exists()) { + byte[] fileContent = Files.readAllBytes(guiFile.toPath()); + InputStream inputStream = new ByteArrayInputStream(fileContent); + loadedGui = ChestGui.load(this, inputStream); + mapPane = new OutlinePane(1, 1, 7, 1); // Define your pane layout + loadedGui.addPane(mapPane); + addMaps(); + } else { + SGM.getInstance().getLogger().log(Level.WARNING, "Could not find mapgui.xml file."); + } + } catch (Exception e) { + SGM.getInstance().getLogger().log(Level.SEVERE, "Error loading mapgui.xml", e); + } + gui = loadedGui; + } + + public void globalClick(InventoryClickEvent event) { + event.setCancelled(true); + } + + public void addMaps() { + List enabledMaps = SGM.getInstance().getLevelManager().enabledMaps.get(this.game); + if (enabledMaps != null) { + for (String mapName : enabledMaps) { + // Create button for each map + ItemStack mapItem = new ItemStack(Material.MAP); + ItemMeta mapMeta = mapItem.getItemMeta(); + mapMeta.setDisplayName(mapName); + mapItem.setItemMeta(mapMeta); + + mapPane.addItem(new GuiItem(mapItem, event -> { + // Handle click event if needed + // Example: navigate to the map or show map details + Player player = (Player) event.getWhoClicked(); + SGM.getInstance().getGameManager().initGame(this.game, player, mapName); + player.closeInventory(); +// player.sendMessage("Clicked on map: " + mapName); + })); + } + } else { + SGM.getInstance().getLogger().log(Level.WARNING, "No maps found for game: " + game); + } + } +} diff --git a/src/main/java/xyz/twovb/sgm/levels/LevelManager.java b/src/main/java/xyz/twovb/sgm/levels/LevelManager.java index 33d39b3..e60893c 100644 --- a/src/main/java/xyz/twovb/sgm/levels/LevelManager.java +++ b/src/main/java/xyz/twovb/sgm/levels/LevelManager.java @@ -1,5 +1,16 @@ package xyz.twovb.sgm.levels; + + +/* + * Created by 2vb - 5/7/2024 + */ + + +/* + * Created by 2vb - 5/7/2024 + */ + /* * Created by 2vb - 4/6/2024 */ @@ -108,6 +119,7 @@ public class LevelManager { File yamlFile = new File(path, "sgm.yml"); try (FileWriter writer = new FileWriter(yamlFile)) { yaml.dump(data, writer); + this.cancel(); } catch (IOException e) { SGM.getInstance().getCLogger().error("Error writing data file: " + e.getMessage()); } @@ -130,10 +142,20 @@ public class LevelManager { // This is probably gonna be funny later player.teleport(Bukkit.getServer().getWorlds().get(0).getSpawnLocation()); } + // TODO: make better if (!Bukkit.isTickingWorlds() && Bukkit.getServer().unloadWorld(world, true)) { if (mapDir.exists()) { FileUtils.deleteDirectory(mapDir); } + File configFile = new File(levelDir + "/sgm.yml"); + YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); + String gameIntName = config.getString("game"); + if (SGM.getInstance().getGameManager().getRegisteredGames().contains(gameIntName)) { + List maps = enabledMaps.get(gameIntName); + if (!maps.contains(name)) { + enabledMaps.get(gameIntName).add(name); + } + } FileUtils.copyDirectory(levelDir, mapDir); FileUtils.delete(new File(mapDir + "/uid.dat")); loadWorld(name, LevelType.LEVEL); @@ -170,8 +192,6 @@ public class LevelManager { block.setType(Material.STONE); } } -// Block block = location.subtract(0, 2, 0).getBlock(); -// block.setType(Material.STONE); world.setSpawnLocation(location); world.setSpawnFlags(false, false); world.setGameRule(GameRule.KEEP_INVENTORY, true); @@ -190,6 +210,7 @@ public class LevelManager { // Load levels from levelPath loadWorldDir(levelPath, LevelType.LEVEL); + loadWorldDir(mapPath, LevelType.MAP); } private void loadWorldDir(String path, LevelType levelType) { @@ -208,8 +229,10 @@ public class LevelManager { if (enabledMaps.containsKey(game) && levelType == LevelType.MAP) { enabledMaps.get(game).add(name); } - // Load the world if sgm.yml exists - loadWorld(file.getName(), levelType); + if (levelType == LevelType.LEVEL) { + // Load the world if sgm.yml exists + loadWorld(file.getName(), levelType); + } } else { SGM.getInstance().getCLogger().log("Skipping directory " + file.getName() + ": sgm.yml not found."); } diff --git a/src/main/resources/games/capturethebrick/messages.yml b/src/main/resources/games/capturethebrick/messages.yml new file mode 100644 index 0000000..0a60f14 --- /dev/null +++ b/src/main/resources/games/capturethebrick/messages.yml @@ -0,0 +1,7 @@ +system: + game: + ready: "&7A new %game% game has started and can now be joined!" + failed: "&7%game% failed %cause%" + player: + join: "&7%player% has joined the game!" + left: "&7%player% has left the game." diff --git a/src/main/resources/guis/activegames.xml b/src/main/resources/guis/activegames.xml new file mode 100644 index 0000000..2c3d4f7 --- /dev/null +++ b/src/main/resources/guis/activegames.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/guis/initgame.xml b/src/main/resources/guis/initgame.xml new file mode 100644 index 0000000..f6ff7ed --- /dev/null +++ b/src/main/resources/guis/initgame.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + Capture The Brick + + + TestGame + + + \ No newline at end of file diff --git a/src/main/resources/guis/joingame.xml b/src/main/resources/guis/joingame.xml new file mode 100644 index 0000000..2332b4a --- /dev/null +++ b/src/main/resources/guis/joingame.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + Capture The Brick + + + TestGame + + + \ No newline at end of file diff --git a/src/main/resources/guis/mapgui.xml b/src/main/resources/guis/mapgui.xml new file mode 100644 index 0000000..8374ed4 --- /dev/null +++ b/src/main/resources/guis/mapgui.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/resources/guis/teampicker.xml b/src/main/resources/guis/teampicker.xml new file mode 100644 index 0000000..dbb4207 --- /dev/null +++ b/src/main/resources/guis/teampicker.xml @@ -0,0 +1,17 @@ + + + + + + + + + Red Team + + + Blue Team + + + \ No newline at end of file diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index 5c8ec1c..e4375e9 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -16,8 +16,6 @@ sgm: cant-start: "&7Game couldn't be started!" cant-join: "&7Could not join this game!" started: "&7Game has started!" - joined: "&7%player% has joined the game!" - left: "&7%player% has left the game." win: "&7Congratulations to %winner% for winning!" level: new: "&7A level with the name %level% has been created."