mirror of
https://github.com/CivMC/Civ.git
synced 2026-07-18 00:20:44 +00:00
add categories and arena cleaner
This commit is contained in:
@@ -2,6 +2,7 @@ package net.civmc.kitpvp;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import net.civmc.kitpvp.anvil.AnvilGui;
|
||||
import net.civmc.kitpvp.arena.ArenaCleaner;
|
||||
import net.civmc.kitpvp.arena.ArenaCommand;
|
||||
import net.civmc.kitpvp.arena.ArenaManager;
|
||||
import net.civmc.kitpvp.arena.MysqlLoader;
|
||||
@@ -55,6 +56,7 @@ public class KitPvpPlugin extends ACivMod {
|
||||
ArenaManager manager = new ArenaManager(this, spawnProvider, new MysqlLoader(source));
|
||||
getCommand("arena").setExecutor(new ArenaCommand(this, new SqlArenaDao(source), manager));
|
||||
getServer().getPluginManager().registerEvents(new RespawnListener(manager), this);
|
||||
Bukkit.getScheduler().runTaskTimer(this, new ArenaCleaner(manager), 20, 20);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package net.civmc.kitpvp.arena;
|
||||
|
||||
import net.civmc.kitpvp.KitPvpPlugin;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class ArenaCleaner implements Runnable {
|
||||
private static final long EMPTY_ARENA_DURATION = TimeUnit.SECONDS.toMillis(20);
|
||||
|
||||
private final Map<LoadedArena, Long> emptyArenas = new HashMap<>();
|
||||
private final ArenaManager arenaManager;
|
||||
|
||||
public ArenaCleaner(ArenaManager arenaManager) {
|
||||
this.arenaManager = arenaManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
for (LoadedArena loadedArena : this.arenaManager.getArenas()) {
|
||||
String arenaName = this.arenaManager.getArenaName(loadedArena.arena().name(), loadedArena.owner());
|
||||
World world = Bukkit.getWorld(arenaName);
|
||||
if (world == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (world.getPlayerCount() == 0) {
|
||||
emptyArenas.putIfAbsent(loadedArena, System.currentTimeMillis());
|
||||
} else {
|
||||
emptyArenas.remove(loadedArena);
|
||||
}
|
||||
}
|
||||
Iterator<Map.Entry<LoadedArena, Long>> iterator = emptyArenas.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<LoadedArena, Long> entry = iterator.next();
|
||||
if (entry.getValue() + EMPTY_ARENA_DURATION < System.currentTimeMillis()) {
|
||||
if (this.arenaManager.getArenas().contains(entry.getKey())) {
|
||||
this.arenaManager.deleteArena(entry.getKey().owner());
|
||||
}
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException ex) {
|
||||
JavaPlugin.getPlugin(KitPvpPlugin.class).getLogger().log(Level.WARNING, "Cleaning arenas", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,7 +78,7 @@ public class ArenaCommand implements CommandExecutor {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
boolean success = dao.newArena(new Arena(arenaName, null, player.getLocation(), icon));
|
||||
boolean success = dao.newArena(new Arena(arenaName, null, null, player.getLocation(), icon));
|
||||
if (success) {
|
||||
player.sendMessage(Component.text("Created arena", NamedTextColor.GREEN));
|
||||
} else {
|
||||
@@ -127,6 +127,27 @@ public class ArenaCommand implements CommandExecutor {
|
||||
}
|
||||
});
|
||||
return true;
|
||||
} else if (args.length > 0 && args[0].equalsIgnoreCase("category")) {
|
||||
if (args.length < 3) {
|
||||
return false;
|
||||
}
|
||||
if (!player.hasPermission("kitpvp.admin")) {
|
||||
player.sendMessage(Component.text("No permission", NamedTextColor.RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
String arenaName = args[1];
|
||||
String category = String.join(" ", Arrays.copyOfRange(args, 2, args.length));
|
||||
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
boolean success = dao.setCategory(arenaName, category);
|
||||
if (success) {
|
||||
player.sendMessage(Component.text("Set category of arena", NamedTextColor.GREEN));
|
||||
} else {
|
||||
player.sendMessage(Component.text("Could not set category of arena. Does it exist?", NamedTextColor.RED));
|
||||
}
|
||||
});
|
||||
return true;
|
||||
} else if (args.length == 0) {
|
||||
new ArenaGui(dao, manager).open(player);
|
||||
return true;
|
||||
|
||||
@@ -61,7 +61,11 @@ public class ArenaManager {
|
||||
}
|
||||
|
||||
public void deleteArena(PlayerProfile owner) {
|
||||
Arena arena = arenas.remove(owner.getId()).arena();
|
||||
LoadedArena removedArena = arenas.remove(owner.getId());
|
||||
if (removedArena == null) {
|
||||
return;
|
||||
}
|
||||
Arena arena = removedArena.arena();
|
||||
String worldName = getArenaName(arena.name(), owner);
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
if (world != null) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.bukkit.Material;
|
||||
public record Arena(
|
||||
String name,
|
||||
String displayName,
|
||||
String category,
|
||||
Location spawn,
|
||||
Material icon
|
||||
) {
|
||||
|
||||
@@ -11,4 +11,6 @@ public interface ArenaDao {
|
||||
boolean deleteArena(String arenaName);
|
||||
|
||||
boolean setDisplayName(String arenaName, String displayName);
|
||||
|
||||
boolean setCategory(String arenaName, String category);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,10 @@ public class SqlArenaDao implements ArenaDao {
|
||||
"""
|
||||
ALTER TABLE arenas ADD COLUMN IF NOT EXISTS display_name VARCHAR(64)
|
||||
""");
|
||||
source.registerMigration(6, false,
|
||||
"""
|
||||
ALTER TABLE arenas ADD COLUMN IF NOT EXISTS category VARCHAR(64)
|
||||
""");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -47,6 +51,7 @@ public class SqlArenaDao implements ArenaDao {
|
||||
arenas.add(new Arena(
|
||||
resultSet.getString("name"),
|
||||
resultSet.getString("display_name"),
|
||||
resultSet.getString("category"),
|
||||
new Location(null, resultSet.getDouble("spawn_x"), resultSet.getDouble("spawn_y"), resultSet.getDouble("spawn_z"), resultSet.getFloat("spawn_yaw"), 0),
|
||||
Material.valueOf(resultSet.getString("icon"))
|
||||
));
|
||||
@@ -102,4 +107,18 @@ public class SqlArenaDao implements ArenaDao {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setCategory(String arenaName, String category) {
|
||||
try (Connection connection = source.getConnection()) {
|
||||
PreparedStatement statement = connection.prepareStatement("UPDATE arenas SET category = ? WHERE name = ?");
|
||||
statement.setString(1, "null".equalsIgnoreCase(category) ? null : category);
|
||||
statement.setString(2, arenaName);
|
||||
|
||||
return statement.executeUpdate() == 1;
|
||||
} catch (SQLException ex) {
|
||||
JavaPlugin.getPlugin(KitPvpPlugin.class).getLogger().log(Level.WARNING, "Error setting display name of arena", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package net.civmc.kitpvp.arena.gui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SequencedMap;
|
||||
import java.util.TreeMap;
|
||||
import net.civmc.kitpvp.KitPvpPlugin;
|
||||
import net.civmc.kitpvp.arena.ArenaManager;
|
||||
import net.civmc.kitpvp.arena.data.Arena;
|
||||
import net.civmc.kitpvp.arena.data.ArenaDao;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import vg.civcraft.mc.civmodcore.inventory.gui.Clickable;
|
||||
import vg.civcraft.mc.civmodcore.inventory.gui.ClickableInventory;
|
||||
|
||||
public class ArenaCategorySelectionGui {
|
||||
|
||||
private final JavaPlugin plugin = JavaPlugin.getPlugin(KitPvpPlugin.class);
|
||||
private final ArenaDao arenaDao;
|
||||
private final ArenaManager manager;
|
||||
|
||||
public ArenaCategorySelectionGui(ArenaDao arenaDao, ArenaManager manager) {
|
||||
this.arenaDao = arenaDao;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
public void open(Player player) {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
List<Arena> arenas = arenaDao.getArenas();
|
||||
Bukkit.getScheduler().runTask(plugin, () -> open(player, arenas));
|
||||
});
|
||||
}
|
||||
|
||||
private void open(Player player, List<Arena> arenas) {
|
||||
if (arenas.isEmpty()) {
|
||||
player.sendMessage(Component.text("No available arenas", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
List<Arena> uncategorised = new ArrayList<>();
|
||||
SequencedMap<String, List<Arena>> arenasByCategory = new TreeMap<>();
|
||||
for (Arena arena : arenas) {
|
||||
if (arena.category() == null) {
|
||||
uncategorised.add(arena);
|
||||
} else {
|
||||
arenasByCategory.computeIfAbsent(arena.category(), k -> new ArrayList<>()).add(arena);
|
||||
}
|
||||
}
|
||||
|
||||
int cats = arenasByCategory.size() + (uncategorised.isEmpty() ? 0 : 1);
|
||||
ClickableInventory inventory = new ClickableInventory(Math.ceilDiv(cats, 9) * 9, "Arena categories");
|
||||
|
||||
int slot = 0;
|
||||
for (Map.Entry<String, List<Arena>> entry : arenasByCategory.entrySet()) {
|
||||
inventory.setSlot(toClickable(entry.getKey(), NamedTextColor.WHITE, entry.getValue()), slot++);
|
||||
}
|
||||
if (!uncategorised.isEmpty()) {
|
||||
inventory.setSlot(toClickable("Uncategorised", NamedTextColor.GRAY, uncategorised), slot);
|
||||
}
|
||||
inventory.showInventory(player, false);
|
||||
}
|
||||
|
||||
private Clickable toClickable(String category, NamedTextColor colour, List<Arena> arenas) {
|
||||
ItemStack item = new ItemStack(Material.ARROW);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.itemName(Component.text(category, colour));
|
||||
item.setItemMeta(meta);
|
||||
return new Clickable(item) {
|
||||
@Override
|
||||
protected void clicked(@NotNull Player clicker) {
|
||||
ArenaSelectionGui gui = new ArenaSelectionGui(arenaDao, ArenaCategorySelectionGui.this, manager);
|
||||
Bukkit.getScheduler().runTask(plugin, () -> gui.open(clicker, arenas));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -82,6 +82,7 @@ public class ArenaGui {
|
||||
protected void onShiftRightClick(@NotNull Player clicker) {
|
||||
if (!hasAccess) {
|
||||
super.onShiftRightClick(clicker);
|
||||
return;
|
||||
}
|
||||
|
||||
new ConfirmDeletionGui(manager, loadedArena.owner(), clicker);
|
||||
@@ -103,7 +104,7 @@ public class ArenaGui {
|
||||
return;
|
||||
}
|
||||
|
||||
new ArenaSelectionGui(dao, manager).open(clicker);
|
||||
new ArenaCategorySelectionGui(dao, manager).open(clicker);
|
||||
}
|
||||
}, 0);
|
||||
view.showScreen();
|
||||
|
||||
@@ -21,20 +21,15 @@ public class ArenaSelectionGui {
|
||||
private final JavaPlugin plugin = JavaPlugin.getPlugin(KitPvpPlugin.class);
|
||||
private final ArenaDao arenaDao;
|
||||
private final ArenaManager manager;
|
||||
private final ArenaCategorySelectionGui parent;
|
||||
|
||||
public ArenaSelectionGui(ArenaDao arenaDao, ArenaManager manager) {
|
||||
public ArenaSelectionGui(ArenaDao arenaDao, ArenaCategorySelectionGui parent, ArenaManager manager) {
|
||||
this.arenaDao = arenaDao;
|
||||
this.parent = parent;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
public void open(Player player) {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
List<Arena> arenas = arenaDao.getArenas();
|
||||
Bukkit.getScheduler().runTask(plugin, () -> open(player, arenas));
|
||||
});
|
||||
}
|
||||
|
||||
private void open(Player player, List<Arena> arenas) {
|
||||
public void open(Player player, List<Arena> arenas) {
|
||||
if (arenas.size() > 54) {
|
||||
throw new IllegalArgumentException("too many arenas");
|
||||
} else if (arenas.isEmpty()) {
|
||||
@@ -51,11 +46,13 @@ public class ArenaSelectionGui {
|
||||
inventory.setSlot(new Clickable(item) {
|
||||
@Override
|
||||
protected void clicked(@NotNull Player clicker) {
|
||||
inventory.setOnClose(null);
|
||||
clicker.closeInventory();
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> manager.createArena(clicker, arena));
|
||||
}
|
||||
}, slot++);
|
||||
}
|
||||
inventory.setOnClose(() -> parent.open(player));
|
||||
inventory.showInventory(player, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public class SetSpawnCommand implements CommandExecutor {
|
||||
if (spawnProvider.setSpawn(location)) {
|
||||
player.sendMessage(Component.text("Set spawn", NamedTextColor.GREEN));
|
||||
} else {
|
||||
player.sendMessage(Component.text("Could not set spawn", NamedTextColor.GREEN));
|
||||
player.sendMessage(Component.text("Could not set spawn", NamedTextColor.RED));
|
||||
}
|
||||
});
|
||||
return true;
|
||||
|
||||
@@ -21,6 +21,7 @@ commands:
|
||||
/<command> create <name> <icon> (administrators only)
|
||||
/<command> delete <name> (administrators only)
|
||||
/<command> displayname <name> <display name> (administrators only)
|
||||
/<command> category <name> <category> (administrators only)
|
||||
spawn: {}
|
||||
setspawn:
|
||||
permission: kitpvp.admin
|
||||
|
||||
Reference in New Issue
Block a user