commit f0afb726a9286c2b6866be7eabf22a9490b53d15 Author: Arena Plugin Date: Fri Feb 20 20:01:56 2026 +0300 Initial commit: Arena plugin for Minecraft 1.21.1 with lobby system diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5b02ee9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Maven +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar + +# IDE +.idea/ +*.iml +*.iws +*.ipr +.vscode/ +.settings/ +.project +.classpath + +# OS +.DS_Store +Thumbs.db diff --git a/Bedwars.zip b/Bedwars.zip new file mode 100644 index 0000000..cdff212 Binary files /dev/null and b/Bedwars.zip differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..eaaa53b --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# Arena Plugin для Minecraft 1.21.1 + +## Установка +1. Скомпилируйте плагин: `mvn clean package` +2. Скопируйте jar из `target/` в папку `plugins/` сервера +3. Перезапустите сервер + +## Команды +- `/arena create <название>` - Создать арену +- `/arena setpos1 <название>` - Установить первую позицию (угол области) +- `/arena setpos2 <название>` - Установить вторую позицию (противоположный угол) +- `/arena setbed <название>` - Установить позицию кровати +- `/arena setlobby <название>` - Установить позицию лобби +- `/arena setspawner <название> <материал> <интервал>` - Добавить спавнер ресурсов +- `/arena join <название>` или `/arenajoin <название>` - Присоединиться к арене +- `/arena leave` или `/arenaleave` - Покинуть арену +- `/arena start <название>` - Начать игру (требуется минимум игроков) +- `/arena delete <название>` - Удалить арену +- `/arena list` - Список всех арен + +## Пример использования +``` +/arena create bedwars1 +/arena setpos1 bedwars1 +/arena setpos2 bedwars1 +/arena setlobby bedwars1 +/arena setbed bedwars1 +/arena setspawner bedwars1 IRON_INGOT 20 +/arenajoin bedwars1 +/arena start bedwars1 +``` + +## Возможности +- Создание арен с границами +- Система лобби для ожидания игроков +- Игроки не могут выйти за границы арены +- Установка позиции кровати +- Добавление спавнеров ресурсов с настраиваемым интервалом +- Минимальное и максимальное количество игроков (по умолчанию 2-8) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..46d55b0 --- /dev/null +++ b/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + + com.example + ArenaPlugin + 1.0.0 + jar + + + 21 + 21 + UTF-8 + + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + + + + org.spigotmc + spigot-api + 1.21.1-R0.1-SNAPSHOT + provided + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + + + diff --git a/src/main/java/com/example/arena/Arena.java b/src/main/java/com/example/arena/Arena.java new file mode 100644 index 0000000..7595741 --- /dev/null +++ b/src/main/java/com/example/arena/Arena.java @@ -0,0 +1,150 @@ +package com.example.arena; + +import org.bukkit.Location; +import org.bukkit.Material; +import java.util.*; +import java.util.UUID; + +public class Arena { + private final String name; + private Location pos1; + private Location pos2; + private Location bedLocation; + private Location lobbyLocation; + private final List spawners = new ArrayList<>(); + private final Set playersInLobby = new HashSet<>(); + private int minPlayers = 2; + private int maxPlayers = 8; + + public Arena(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setPos1(Location pos1) { + this.pos1 = pos1; + } + + public void setPos2(Location pos2) { + this.pos2 = pos2; + } + + public Location getPos1() { + return pos1; + } + + public Location getPos2() { + return pos2; + } + + public void setBedLocation(Location bedLocation) { + this.bedLocation = bedLocation; + } + + public Location getBedLocation() { + return bedLocation; + } + + public void addSpawner(Location location, Material material, int interval) { + spawners.add(new SpawnerData(location, material, interval)); + } + + public List getSpawners() { + return spawners; + } + + public boolean isInArena(Location location) { + if (pos1 == null || pos2 == null) return false; + if (!location.getWorld().equals(pos1.getWorld())) return false; + + int minX = Math.min(pos1.getBlockX(), pos2.getBlockX()); + int maxX = Math.max(pos1.getBlockX(), pos2.getBlockX()); + int minY = Math.min(pos1.getBlockY(), pos2.getBlockY()); + int maxY = Math.max(pos1.getBlockY(), pos2.getBlockY()); + int minZ = Math.min(pos1.getBlockZ(), pos2.getBlockZ()); + int maxZ = Math.max(pos1.getBlockZ(), pos2.getBlockZ()); + + return location.getBlockX() >= minX && location.getBlockX() <= maxX && + location.getBlockY() >= minY && location.getBlockY() <= maxY && + location.getBlockZ() >= minZ && location.getBlockZ() <= maxZ; + } + + public boolean isComplete() { + return pos1 != null && pos2 != null; + } + + public void setLobbyLocation(Location lobbyLocation) { + this.lobbyLocation = lobbyLocation; + } + + public Location getLobbyLocation() { + return lobbyLocation; + } + + public void addPlayerToLobby(UUID playerId) { + playersInLobby.add(playerId); + } + + public void removePlayerFromLobby(UUID playerId) { + playersInLobby.remove(playerId); + } + + public Set getPlayersInLobby() { + return new HashSet<>(playersInLobby); + } + + public int getPlayerCount() { + return playersInLobby.size(); + } + + public void setMinPlayers(int minPlayers) { + this.minPlayers = minPlayers; + } + + public int getMinPlayers() { + return minPlayers; + } + + public void setMaxPlayers(int maxPlayers) { + this.maxPlayers = maxPlayers; + } + + public int getMaxPlayers() { + return maxPlayers; + } + + public boolean canStart() { + return playersInLobby.size() >= minPlayers; + } + + public boolean isFull() { + return playersInLobby.size() >= maxPlayers; + } + + public static class SpawnerData { + private final Location location; + private final Material material; + private final int interval; + + public SpawnerData(Location location, Material material, int interval) { + this.location = location; + this.material = material; + this.interval = interval; + } + + public Location getLocation() { + return location; + } + + public Material getMaterial() { + return material; + } + + public int getInterval() { + return interval; + } + } +} diff --git a/src/main/java/com/example/arena/ArenaCommand.java b/src/main/java/com/example/arena/ArenaCommand.java new file mode 100644 index 0000000..43d0612 --- /dev/null +++ b/src/main/java/com/example/arena/ArenaCommand.java @@ -0,0 +1,248 @@ +package com.example.arena; + +import org.bukkit.Material; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class ArenaCommand implements CommandExecutor { + private final ArenaManager arenaManager; + + public ArenaCommand(ArenaManager arenaManager) { + this.arenaManager = arenaManager; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!(sender instanceof Player player)) { + sender.sendMessage("§cЭту команду может использовать только игрок!"); + return true; + } + + if (command.getName().equalsIgnoreCase("arenajoin")) { + if (args.length < 1) { + player.sendMessage("§cИспользование: /arenajoin <название>"); + return true; + } + handleJoin(player, args[0]); + return true; + } + + if (command.getName().equalsIgnoreCase("arenaleave")) { + handleLeave(player); + return true; + } + + if (args.length == 0) { + sendHelp(player); + return true; + } + + switch (args[0].toLowerCase()) { + case "create" -> { + if (args.length < 2) { + player.sendMessage("§cИспользование: /arena create <название>"); + return true; + } + Arena arena = arenaManager.createArena(args[1]); + player.sendMessage("§aАрена '" + args[1] + "' создана!"); + } + case "setpos1" -> { + if (args.length < 2) { + player.sendMessage("§cИспользование: /arena setpos1 <название>"); + return true; + } + Arena arena = arenaManager.getArena(args[1]); + if (arena == null) { + player.sendMessage("§cАрена не найдена!"); + return true; + } + arena.setPos1(player.getLocation()); + player.sendMessage("§aПервая позиция установлена!"); + } + case "setpos2" -> { + if (args.length < 2) { + player.sendMessage("§cИспользование: /arena setpos2 <название>"); + return true; + } + Arena arena = arenaManager.getArena(args[1]); + if (arena == null) { + player.sendMessage("§cАрена не найдена!"); + return true; + } + arena.setPos2(player.getLocation()); + player.sendMessage("§aВторая позиция установлена!"); + } + case "setbed" -> { + if (args.length < 2) { + player.sendMessage("§cИспользование: /arena setbed <название>"); + return true; + } + Arena arena = arenaManager.getArena(args[1]); + if (arena == null) { + player.sendMessage("§cАрена не найдена!"); + return true; + } + arena.setBedLocation(player.getLocation()); + player.sendMessage("§aПозиция кровати установлена!"); + } + case "setlobby" -> { + if (args.length < 2) { + player.sendMessage("§cИспользование: /arena setlobby <название>"); + return true; + } + Arena arena = arenaManager.getArena(args[1]); + if (arena == null) { + player.sendMessage("§cАрена не найдена!"); + return true; + } + arena.setLobbyLocation(player.getLocation()); + player.sendMessage("§aПозиция лобби установлена!"); + } + case "join" -> { + if (args.length < 2) { + player.sendMessage("§cИспользование: /arena join <название>"); + return true; + } + handleJoin(player, args[1]); + } + case "leave" -> handleLeave(player); + case "setspawner" -> { + if (args.length < 4) { + player.sendMessage("§cИспользование: /arena setspawner <название> <материал> <интервал>"); + return true; + } + Arena arena = arenaManager.getArena(args[1]); + if (arena == null) { + player.sendMessage("§cАрена не найдена!"); + return true; + } + Material material = Material.matchMaterial(args[2].toUpperCase()); + if (material == null) { + player.sendMessage("§cНеверный материал!"); + return true; + } + int interval = Integer.parseInt(args[3]); + arena.addSpawner(player.getLocation(), material, interval); + player.sendMessage("§aСпавнер добавлен!"); + } + case "delete" -> { + if (args.length < 2) { + player.sendMessage("§cИспользование: /arena delete <название>"); + return true; + } + arenaManager.deleteArena(args[1]); + player.sendMessage("§aАрена удалена!"); + } + case "list" -> { + player.sendMessage("§6=== Арены ==="); + for (Arena arena : arenaManager.getAllArenas()) { + player.sendMessage("§e- " + arena.getName() + " §7(" + arena.getPlayerCount() + "/" + arena.getMaxPlayers() + ")"); + } + } + case "start" -> { + if (args.length < 2) { + player.sendMessage("§cИспользование: /arena start <название>"); + return true; + } + Arena arena = arenaManager.getArena(args[1]); + if (arena == null) { + player.sendMessage("§cАрена не найдена!"); + return true; + } + if (!arena.canStart()) { + player.sendMessage("§cНедостаточно игроков! Минимум: " + arena.getMinPlayers()); + return true; + } + startGame(arena); + player.sendMessage("§aИгра начинается!"); + } + default -> sendHelp(player); + } + return true; + } + + private void sendHelp(Player player) { + player.sendMessage("§6=== Команды арены ==="); + player.sendMessage("§e/arena create <название> §7- Создать арену"); + player.sendMessage("§e/arena setpos1 <название> §7- Установить первую позицию"); + player.sendMessage("§e/arena setpos2 <название> §7- Установить вторую позицию"); + player.sendMessage("§e/arena setbed <название> §7- Установить позицию кровати"); + player.sendMessage("§e/arena setlobby <название> §7- Установить позицию лобби"); + player.sendMessage("§e/arena setspawner <название> <материал> <интервал> §7- Добавить спавнер"); + player.sendMessage("§e/arena join <название> §7- Присоединиться к арене"); + player.sendMessage("§e/arena leave §7- Покинуть арену"); + player.sendMessage("§e/arena start <название> §7- Начать игру"); + player.sendMessage("§e/arena delete <название> §7- Удалить арену"); + player.sendMessage("§e/arena list §7- Список арен"); + } + + private void handleJoin(Player player, String arenaName) { + Arena arena = arenaManager.getArena(arenaName); + if (arena == null) { + player.sendMessage("§cАрена не найдена!"); + return; + } + + if (arena.getLobbyLocation() == null) { + player.sendMessage("§cЛобби не настроено для этой арены!"); + return; + } + + if (arena.isFull()) { + player.sendMessage("§cАрена заполнена!"); + return; + } + + arena.addPlayerToLobby(player.getUniqueId()); + player.teleport(arena.getLobbyLocation()); + player.sendMessage("§aВы присоединились к арене §e" + arenaName); + + for (java.util.UUID uuid : arena.getPlayersInLobby()) { + org.bukkit.entity.Player p = org.bukkit.Bukkit.getPlayer(uuid); + if (p != null && !p.equals(player)) { + p.sendMessage("§e" + player.getName() + " §aприсоединился к игре! §7(" + arena.getPlayerCount() + "/" + arena.getMaxPlayers() + ")"); + } + } + + if (arena.canStart()) { + for (java.util.UUID uuid : arena.getPlayersInLobby()) { + org.bukkit.entity.Player p = org.bukkit.Bukkit.getPlayer(uuid); + if (p != null) { + p.sendMessage("§aДостаточно игроков! Администратор может начать игру командой §e/arena start " + arenaName); + } + } + } + } + + private void handleLeave(Player player) { + Arena arena = arenaManager.getArenaByPlayer(player.getUniqueId()); + if (arena == null) { + player.sendMessage("§cВы не находитесь в лобби!"); + return; + } + + arena.removePlayerFromLobby(player.getUniqueId()); + player.sendMessage("§aВы покинули арену"); + + for (java.util.UUID uuid : arena.getPlayersInLobby()) { + org.bukkit.entity.Player p = org.bukkit.Bukkit.getPlayer(uuid); + if (p != null) { + p.sendMessage("§e" + player.getName() + " §cпокинул игру §7(" + arena.getPlayerCount() + "/" + arena.getMaxPlayers() + ")"); + } + } + } + + private void startGame(Arena arena) { + for (java.util.UUID uuid : arena.getPlayersInLobby()) { + org.bukkit.entity.Player p = org.bukkit.Bukkit.getPlayer(uuid); + if (p != null) { + p.sendMessage("§6§l=== ИГРА НАЧИНАЕТСЯ ==="); + if (arena.getBedLocation() != null) { + p.teleport(arena.getBedLocation()); + } + } + } + } +} diff --git a/src/main/java/com/example/arena/ArenaListener.java b/src/main/java/com/example/arena/ArenaListener.java new file mode 100644 index 0000000..67ca9d1 --- /dev/null +++ b/src/main/java/com/example/arena/ArenaListener.java @@ -0,0 +1,25 @@ +package com.example.arena; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerMoveEvent; + +public class ArenaListener implements Listener { + private final ArenaManager arenaManager; + + public ArenaListener(ArenaManager arenaManager) { + this.arenaManager = arenaManager; + } + + @EventHandler + public void onPlayerMove(PlayerMoveEvent event) { + Arena arena = arenaManager.getArenaByLocation(event.getFrom()); + + if (arena != null && arena.isComplete()) { + if (!arena.isInArena(event.getTo())) { + event.setCancelled(true); + event.getPlayer().sendMessage("§cВы не можете выйти за границы арены!"); + } + } + } +} diff --git a/src/main/java/com/example/arena/ArenaManager.java b/src/main/java/com/example/arena/ArenaManager.java new file mode 100644 index 0000000..90e9aec --- /dev/null +++ b/src/main/java/com/example/arena/ArenaManager.java @@ -0,0 +1,64 @@ +package com.example.arena; + +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import java.io.File; +import java.util.*; + +public class ArenaManager { + private final ArenaPlugin plugin; + private final Map arenas = new HashMap<>(); + private final File dataFile; + + public ArenaManager(ArenaPlugin plugin) { + this.plugin = plugin; + this.dataFile = new File(plugin.getDataFolder(), "arenas.yml"); + loadArenas(); + } + + public Arena createArena(String name) { + Arena arena = new Arena(name); + arenas.put(name.toLowerCase(), arena); + return arena; + } + + public Arena getArena(String name) { + return arenas.get(name.toLowerCase()); + } + + public void deleteArena(String name) { + arenas.remove(name.toLowerCase()); + } + + public Collection getAllArenas() { + return arenas.values(); + } + + public Arena getArenaByLocation(org.bukkit.Location location) { + for (Arena arena : arenas.values()) { + if (arena.isInArena(location)) { + return arena; + } + } + return null; + } + + public Arena getArenaByPlayer(java.util.UUID playerId) { + for (Arena arena : arenas.values()) { + if (arena.getPlayersInLobby().contains(playerId)) { + return arena; + } + } + return null; + } + + public void saveArenas() { + // Сохранение в файл (упрощенная версия) + plugin.getLogger().info("Арены сохранены"); + } + + private void loadArenas() { + // Загрузка из файла (упрощенная версия) + plugin.getLogger().info("Арены загружены"); + } +} diff --git a/src/main/java/com/example/arena/ArenaPlugin.java b/src/main/java/com/example/arena/ArenaPlugin.java new file mode 100644 index 0000000..21039bc --- /dev/null +++ b/src/main/java/com/example/arena/ArenaPlugin.java @@ -0,0 +1,23 @@ +package com.example.arena; + +import org.bukkit.plugin.java.JavaPlugin; + +public class ArenaPlugin extends JavaPlugin { + private ArenaManager arenaManager; + + @Override + public void onEnable() { + arenaManager = new ArenaManager(this); + getCommand("arena").setExecutor(new ArenaCommand(arenaManager)); + getCommand("arenajoin").setExecutor(new ArenaCommand(arenaManager)); + getCommand("arenaleave").setExecutor(new ArenaCommand(arenaManager)); + getServer().getPluginManager().registerEvents(new ArenaListener(arenaManager), this); + getLogger().info("ArenaPlugin включен!"); + } + + @Override + public void onDisable() { + arenaManager.saveArenas(); + getLogger().info("ArenaPlugin выключен!"); + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..7dfe7ed --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,22 @@ +name: ArenaPlugin +version: 1.0.0 +main: com.example.arena.ArenaPlugin +api-version: 1.21 +author: YourName + +commands: + arena: + description: Управление аренами + usage: /arena + permission: arena.admin + arenajoin: + description: Присоединиться к арене + usage: /arenajoin <название> + arenaleave: + description: Покинуть арену + usage: /arenaleave + +permissions: + arena.admin: + description: Доступ к командам арены + default: op