Add GUI framework for class selection in CTF
Introduced a GUI system to facilitate class selection in the CTF game. This includes an abstract GUIInventory, GUIListener for event handling, and a ClassSelectionGUI for selecting classes. Also, added the "selectclass" command and integrated the GUI with game mechanics for improved player interaction.
This commit is contained in:
parent
6a9721d0e7
commit
73c11ab1ca
|
|
@ -10,6 +10,7 @@ import com.alttd.ctf.events.OnSnowballHit;
|
|||
import com.alttd.ctf.flag.Flag;
|
||||
import com.alttd.ctf.flag.FlagTryCaptureEvent;
|
||||
import com.alttd.ctf.game.GameManager;
|
||||
import com.alttd.ctf.gui.GUIListener;
|
||||
import com.alttd.ctf.json_config.JacksonConfig;
|
||||
import com.alttd.ctf.json_config.JsonConfigManager;
|
||||
import com.alttd.ctf.team.Team;
|
||||
|
|
@ -69,6 +70,7 @@ public class Main extends JavaPlugin {
|
|||
pluginManager.registerEvents(new FlagTryCaptureEvent(flag), this);
|
||||
pluginManager.registerEvents(new OnPlayerDeath(gameManager), this);
|
||||
pluginManager.registerEvents(new OnPlayerJoin(gameManager, flag), this);
|
||||
pluginManager.registerEvents(new GUIListener(), this);
|
||||
}
|
||||
|
||||
private void registerTeams() {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
package com.alttd.ctf.commands;
|
||||
|
||||
import com.alttd.ctf.Main;
|
||||
import com.alttd.ctf.commands.subcommands.ChangeTeam;
|
||||
import com.alttd.ctf.commands.subcommands.CreateTeam;
|
||||
import com.alttd.ctf.commands.subcommands.Reload;
|
||||
import com.alttd.ctf.commands.subcommands.Start;
|
||||
import com.alttd.ctf.commands.subcommands.*;
|
||||
import com.alttd.ctf.config.Messages;
|
||||
import com.alttd.ctf.flag.Flag;
|
||||
import com.alttd.ctf.game.GameManager;
|
||||
|
|
@ -39,6 +36,7 @@ public class CommandManager implements CommandExecutor, TabExecutor {
|
|||
new ChangeTeam(gameManager),
|
||||
new Start(gameManager, flag),
|
||||
new CreateTeam(main, gameManager),
|
||||
new SelectClass(gameManager),
|
||||
new Reload(main)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
package com.alttd.ctf.commands.subcommands;
|
||||
|
||||
import com.alttd.ctf.commands.SubCommand;
|
||||
import com.alttd.ctf.config.Messages;
|
||||
import com.alttd.ctf.game.GameManager;
|
||||
import com.alttd.ctf.game_class.GameClass;
|
||||
import com.alttd.ctf.game_class.creation.FighterCreator;
|
||||
import com.alttd.ctf.gui.ClassSelectionGUI;
|
||||
import com.alttd.ctf.team.TeamPlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class SelectClass extends SubCommand {
|
||||
|
||||
private final GameManager gameManager;
|
||||
private final HashMap<Integer, List<GameClass>> gameClasses;
|
||||
|
||||
public SelectClass(GameManager gameManager) {
|
||||
this.gameManager = gameManager;
|
||||
this.gameClasses = new HashMap<>();
|
||||
gameManager.getTeams().forEach(team -> {
|
||||
gameClasses.computeIfAbsent(team.getId(), teamId -> new ArrayList<>()).add(FighterCreator.createFighter(team.getColor()));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onCommand(CommandSender commandSender, String[] args) {
|
||||
if (!(commandSender instanceof Player player)) {
|
||||
commandSender.sendRichMessage(Messages.GENERIC.PLAYER_ONLY);
|
||||
return -1;
|
||||
}
|
||||
if (gameManager.getGamePhase().isEmpty()) {
|
||||
commandSender.sendRichMessage("<red>CTF has to be running to select a class.</red>");
|
||||
return 0;
|
||||
}
|
||||
Optional<TeamPlayer> optionalTeamPlayer = gameManager.getTeamPlayer(player.getUniqueId());
|
||||
if (optionalTeamPlayer.isEmpty()) {
|
||||
commandSender.sendRichMessage("<red>You have to be in a CTF team to select a class.</red>");
|
||||
return 0;
|
||||
}
|
||||
TeamPlayer teamPlayer = optionalTeamPlayer.get();
|
||||
if (teamPlayer.getTeam().getSpawnLocation().distance(player.getLocation()) > 15) {
|
||||
commandSender.sendRichMessage("<red>You have to be near your spawn to change classes.</red>");
|
||||
return 0;
|
||||
}
|
||||
new ClassSelectionGUI(gameClasses.get(teamPlayer.getTeam().getId()), teamPlayer)
|
||||
.open(player);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "selectclass";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabComplete(CommandSender commandSender, String[] args) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpMessage() {
|
||||
return Messages.HELP.SELECT_CLASS;
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ public class Messages extends AbstractConfig {
|
|||
public static String CHANGE_TEAM = "<green>Change a players team: <gold>/ctf changeteam <player> <team></gold></green>";
|
||||
public static String CREATE_TEAM = "<green>Create a team: <gold>/ctf createteam <team_name> <hex_color></gold></green>";
|
||||
public static String START = "<green>Start a new game: <gold>/ctf start <time_in_minutes></gold></green>";
|
||||
public static String SELECT_CLASS = "<green>Open class selection: <gold>/ctf selectclass</gold></green>";
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static void load() {
|
||||
|
|
@ -35,6 +36,7 @@ public class Messages extends AbstractConfig {
|
|||
CHANGE_TEAM = config.getString(prefix, "change-team", CHANGE_TEAM);
|
||||
CREATE_TEAM = config.getString(prefix, "create-team", CREATE_TEAM);
|
||||
START = config.getString(prefix, "start", START);
|
||||
SELECT_CLASS = config.getString(prefix, "select-class", SELECT_CLASS);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import com.alttd.ctf.team.TeamColor;
|
|||
import com.alttd.ctf.team.TeamPlayer;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Material;
|
||||
|
|
@ -13,6 +15,7 @@ import org.bukkit.entity.Player;
|
|||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.LeatherArmorMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -21,7 +24,10 @@ public abstract class GameClass {
|
|||
|
||||
private final List<Material> armor;
|
||||
private final List<ItemStack> tools;
|
||||
@Getter
|
||||
private final ItemStack displayItem;
|
||||
@Getter
|
||||
private final Component className;
|
||||
private final double health;
|
||||
//Delay in ticks between throws (prevents auto clickers)
|
||||
@Getter
|
||||
|
|
@ -30,7 +36,7 @@ public abstract class GameClass {
|
|||
@Getter
|
||||
private final int damage;
|
||||
|
||||
protected GameClass(List<Material> armor, List<ItemStack> tools, ItemStack displayItem, double health, int throwTickSpeed, int damage) {
|
||||
protected GameClass(@NotNull List<Material> armor, @NotNull List<ItemStack> tools, @NotNull ItemStack displayItem, double health, int throwTickSpeed, int damage) {
|
||||
if (armor.size() != 4) {
|
||||
throw new IllegalArgumentException("Armor has to have 4 entries");
|
||||
}
|
||||
|
|
@ -40,6 +46,11 @@ public abstract class GameClass {
|
|||
this.health = health;
|
||||
this.throwTickSpeed = throwTickSpeed;
|
||||
this.damage = damage;
|
||||
ItemMeta itemMeta = displayItem.getItemMeta();
|
||||
if (itemMeta == null) {
|
||||
throw new IllegalArgumentException("Display item has no item meta");
|
||||
}
|
||||
this.className = itemMeta.displayName();
|
||||
}
|
||||
|
||||
public void apply(TeamPlayer teamPlayer) {
|
||||
|
|
@ -64,6 +75,8 @@ public abstract class GameClass {
|
|||
|
||||
player.updateInventory();
|
||||
teamPlayer.setGameClass(this);
|
||||
player.sendRichMessage("You selected the <class_name> class", Placeholder.component("class_name", className));
|
||||
player.teleportAsync(teamPlayer.getTeam().getSpawnLocation());
|
||||
}
|
||||
|
||||
private void setArmor(Player player, int r, int g, int b) {
|
||||
|
|
@ -78,10 +91,6 @@ public abstract class GameClass {
|
|||
}).toArray(ItemStack[]::new));
|
||||
}
|
||||
|
||||
ItemStack getDisplayItem() {
|
||||
return displayItem;
|
||||
}
|
||||
|
||||
public void setArmor(Player player, TeamPlayer teamPlayer) {
|
||||
TeamColor color = teamPlayer.getTeam().getColor();
|
||||
setArmor(player, color.r(), color.g(), color.b());
|
||||
|
|
|
|||
29
src/main/java/com/alttd/ctf/gui/ClassSelectionGUI.java
Normal file
29
src/main/java/com/alttd/ctf/gui/ClassSelectionGUI.java
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package com.alttd.ctf.gui;
|
||||
|
||||
import com.alttd.ctf.game_class.GameClass;
|
||||
import com.alttd.ctf.team.TeamPlayer;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ClassSelectionGUI extends GUIInventory {
|
||||
|
||||
public ClassSelectionGUI(@NotNull List<GameClass> gameClasses, @NotNull TeamPlayer teamPlayer) {
|
||||
super(InventoryType.CHEST, teamPlayer.getTeam().getName().append(MiniMessage.miniMessage().deserialize(" - class selection")));
|
||||
createClassSelection(gameClasses, teamPlayer);
|
||||
}
|
||||
|
||||
private void createClassSelection(@NotNull List<GameClass> gameClasses, @NotNull TeamPlayer teamPlayer) {
|
||||
int pos = (9 + (9 - gameClasses.size()) / 2);
|
||||
for (GameClass gameClass : gameClasses) {
|
||||
setItem(pos++, gameClass.getDisplayItem(), player -> {
|
||||
gameClass.apply(teamPlayer);
|
||||
player.closeInventory(InventoryCloseEvent.Reason.PLUGIN);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
19
src/main/java/com/alttd/ctf/gui/GUI.java
Normal file
19
src/main/java/com/alttd/ctf/gui/GUI.java
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
package com.alttd.ctf.gui;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.Merchant;
|
||||
import org.bukkit.inventory.MerchantInventory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface GUI {
|
||||
HashMap<UUID, GUI> GUIByUUID = new HashMap<>();
|
||||
|
||||
void open(Player player);
|
||||
|
||||
GUIAction getGuiAction(int slot);
|
||||
|
||||
Inventory getInventory();
|
||||
}
|
||||
7
src/main/java/com/alttd/ctf/gui/GUIAction.java
Normal file
7
src/main/java/com/alttd/ctf/gui/GUIAction.java
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
package com.alttd.ctf.gui;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface GUIAction {
|
||||
void click(Player player);
|
||||
}
|
||||
46
src/main/java/com/alttd/ctf/gui/GUIInventory.java
Normal file
46
src/main/java/com/alttd/ctf/gui/GUIInventory.java
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
package com.alttd.ctf.gui;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.Merchant;
|
||||
import org.bukkit.inventory.MerchantInventory;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public abstract class GUIInventory implements GUI {
|
||||
|
||||
@Getter
|
||||
protected final Inventory inventory;
|
||||
protected final HashMap<Integer, GUIAction> guiActions;
|
||||
|
||||
public GUIInventory(InventoryType type, Component name) {
|
||||
inventory = Bukkit.createInventory(null, type, name);
|
||||
guiActions = new HashMap<>();
|
||||
}
|
||||
|
||||
public void setItem(int slot, ItemStack stack, GUIAction action) {
|
||||
this.inventory.setItem(slot, stack);
|
||||
if (action != null) {
|
||||
guiActions.put(slot, action);
|
||||
}
|
||||
}
|
||||
|
||||
public void setItem(int slot, ItemStack stack) {
|
||||
setItem(slot, stack, null);
|
||||
}
|
||||
|
||||
public void open(Player player) {
|
||||
player.openInventory(inventory);
|
||||
GUIByUUID.put(player.getUniqueId(), this);
|
||||
}
|
||||
|
||||
public GUIAction getGuiAction(int slot) {
|
||||
return guiActions.get(slot);
|
||||
}
|
||||
|
||||
}
|
||||
60
src/main/java/com/alttd/ctf/gui/GUIListener.java
Normal file
60
src/main/java/com/alttd/ctf/gui/GUIListener.java
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
package com.alttd.ctf.gui;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
|
||||
public class GUIListener implements Listener {
|
||||
|
||||
/**
|
||||
* Handles clicking inside a gui
|
||||
* @param event gui click event
|
||||
*/
|
||||
@EventHandler
|
||||
public void onClick(InventoryClickEvent event){
|
||||
if (!(event.getWhoClicked() instanceof Player player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
GUI gui = GUI.GUIByUUID.get(player.getUniqueId());
|
||||
if (gui == null) {
|
||||
return;
|
||||
}
|
||||
if (gui.getInventory() != null) {
|
||||
if (!gui.getInventory().equals(event.getInventory())) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
Inventory clickedInventory = event.getClickedInventory();
|
||||
if (clickedInventory == null || clickedInventory.getType().equals(InventoryType.PLAYER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
GUIAction action = gui.getGuiAction(event.getSlot());
|
||||
|
||||
if (action != null) {
|
||||
action.click(player);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onClose(InventoryCloseEvent event) {
|
||||
GUI.GUIByUUID.remove(event.getPlayer().getUniqueId());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(PlayerQuitEvent event){
|
||||
GUI.GUIByUUID.remove(event.getPlayer().getUniqueId());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
#Fri Feb 07 22:07:29 CET 2025
|
||||
buildNumber=5
|
||||
#Fri Feb 07 23:09:43 CET 2025
|
||||
buildNumber=8
|
||||
version=0.1
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user