diff --git a/src/main/java/moe/sdg/PluginSDG/GameManager.java b/src/main/java/moe/sdg/PluginSDG/GameManager.java index b1a3e53..303135b 100644 --- a/src/main/java/moe/sdg/PluginSDG/GameManager.java +++ b/src/main/java/moe/sdg/PluginSDG/GameManager.java @@ -1,22 +1,44 @@ package moe.sdg.PluginSDG; +import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader; +import com.sk89q.worldedit.function.operation.Operation; +import com.sk89q.worldedit.function.operation.Operations; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.session.ClipboardHolder; import moe.sdg.PluginSDG.commands.SDGCommand; +import moe.sdg.PluginSDG.exceptions.InvalidMapException; +import moe.sdg.PluginSDG.exceptions.MapNotFoundException; import moe.sdg.PluginSDG.games.DeathMatch; import moe.sdg.PluginSDG.commands.HubCommand; import moe.sdg.PluginSDG.commands.SetHubCommand; -import org.bukkit.Bukkit; -import org.bukkit.Location; +import org.bukkit.*; import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.generator.BlockPopulator; +import org.bukkit.generator.ChunkGenerator; import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.util.Vector; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.util.ArrayList; +import java.util.List; +import java.util.Random; import java.util.stream.Collectors; public class GameManager extends JavaPlugin { private ArrayList _games; private WorldEditPlugin _worldEdit; + private Vector nextGameLocation = new Vector(0, 150, 0); @SuppressWarnings("ConstantConditions") @Override @@ -59,7 +81,7 @@ public class GameManager extends JavaPlugin switch (type) { case DeathMatch: - DeathMatch match = new DeathMatch(this, map, gameName != null ? gameName : this.generateNewName()); + DeathMatch match = new DeathMatch(this, map, gameName); this._games.add(match); return match; @@ -68,21 +90,6 @@ public class GameManager extends JavaPlugin } } - public MiniGame createGame(GameType type, String map) - { - return this.createGame(type,map,null); - } - - //! @brief generate a new possible game name of the form - //! @return - private String generateNewName() - { - String name = "Unnamed " + Math.random(); - if (this.getGameByName(name) != null) - return this.generateNewName(); - return name; - } - //! @brief delete a game //! @param game the game to be deleted public void deleteGame(MiniGame game) @@ -112,4 +119,70 @@ public class GameManager extends JavaPlugin .findFirst() .orElse(null); } + + public GameMap generateMap(String name) + { + File dir = new File(this.getDataFolder(), "map"); + if (!dir.exists()) + throw new MapNotFoundException(); + + File file = new File(dir, name + ".schematic"); + if (!file.exists()) + throw new MapNotFoundException(); + ClipboardFormat format = ClipboardFormats.findByFile(file); + if (format == null) + throw new InvalidMapException(); + try (ClipboardReader reader = format.getReader(new FileInputStream(file))) + { + Clipboard clipboard = reader.read(); + World world = this._getGameWorld(); + try (EditSession editSession = WorldEdit.getInstance() + .getEditSessionFactory() + .getEditSession(BukkitAdapter.adapt(world), -1)) + { + Operation operation = new ClipboardHolder(clipboard) + .createPaste(editSession) + .to(BlockVector3.at(nextGameLocation.getX(), nextGameLocation.getY(), nextGameLocation.getZ())) + .build(); + Operations.complete(operation); + clipboard.setOrigin(BlockVector3.at(nextGameLocation.getX(), nextGameLocation.getY(), nextGameLocation.getZ())); + nextGameLocation.add(new Vector(200, 0, 0)); + return new GameMap(clipboard, world); + } + } + catch (IOException | WorldEditException e) + { + e.printStackTrace(); + throw new InvalidMapException(); + } + } + + private World _getGameWorld() + { + World world = Bukkit.getWorld("sdg_games"); + if (world != null) + return world; + return Bukkit.createWorld(new WorldCreator("sdg_games") + .type(WorldType.FLAT) + .generator(new ChunkGenerator() + { + @Override + public ChunkData generateChunkData(World world, Random random, int x, int z, BiomeGrid biome) + { + return createChunkData(world); + } + + @Override + public boolean shouldGenerateMobs() + { + return false; + } + + @Override + public List getDefaultPopulators(World world) + { + return new ArrayList<>(); + } + })); + } } diff --git a/src/main/java/moe/sdg/PluginSDG/GameMap.java b/src/main/java/moe/sdg/PluginSDG/GameMap.java new file mode 100644 index 0000000..eafea29 --- /dev/null +++ b/src/main/java/moe/sdg/PluginSDG/GameMap.java @@ -0,0 +1,34 @@ +package moe.sdg.PluginSDG; + +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockType; +import org.bukkit.Location; +import org.bukkit.World; +import java.util.ArrayList; + +public class GameMap +{ + public Location lobbyLocation; + + public ArrayList spawnLocations; + + public GameMap() { } + + public GameMap(Clipboard clipboard, World world) + { + BlockVector3 o = clipboard.getOrigin(); + this.lobbyLocation = new Location(world, o.getX(), o.getY(), o.getZ()); + for (BlockVector3 b : clipboard.getRegion()) + { + BlockState state = clipboard.getBlock(b); + if (state.getBlockType() == BlockType.REGISTRY.get("minecraft:respawn_anchor")) + { + System.out.println("RESPAWN BLOCK"); + this.spawnLocations.add(new Location(world, b.getX(), b.getY(), b.getZ())); + } + } + } +} diff --git a/src/main/java/moe/sdg/PluginSDG/GameType.java b/src/main/java/moe/sdg/PluginSDG/GameType.java index d2e3bda..448ffba 100644 --- a/src/main/java/moe/sdg/PluginSDG/GameType.java +++ b/src/main/java/moe/sdg/PluginSDG/GameType.java @@ -2,5 +2,6 @@ package moe.sdg.PluginSDG; public enum GameType { + None, DeathMatch } diff --git a/src/main/java/moe/sdg/PluginSDG/MiniGame.java b/src/main/java/moe/sdg/PluginSDG/MiniGame.java index 8dbea21..a565a02 100644 --- a/src/main/java/moe/sdg/PluginSDG/MiniGame.java +++ b/src/main/java/moe/sdg/PluginSDG/MiniGame.java @@ -8,17 +8,17 @@ public abstract class MiniGame { private final ArrayList _players; private final GameManager _manager; - private final Location _lobbyLocation; + private final GameMap _map; private final String name; protected int _maxPlayer = 4; protected boolean enforceMaxPlayer = true; - public MiniGame(GameManager manager, String name) + public MiniGame(GameManager manager, String mapName, String name) { this._manager = manager; - this._lobbyLocation = null; - this._players = new ArrayList(); + this._map = this._manager.generateMap(mapName);; + this._players = new ArrayList<>(); this.name = name; } @@ -41,7 +41,7 @@ public abstract class MiniGame if (this.getMaxPlayers() < this.getCurrentPlayers() + 1) return false; this._players.add(player); - player.teleport(this._lobbyLocation); + player.teleport(this._map.lobbyLocation); return true; } diff --git a/src/main/java/moe/sdg/PluginSDG/TeamMiniGame.java b/src/main/java/moe/sdg/PluginSDG/TeamMiniGame.java index 5f3a04a..67fe245 100644 --- a/src/main/java/moe/sdg/PluginSDG/TeamMiniGame.java +++ b/src/main/java/moe/sdg/PluginSDG/TeamMiniGame.java @@ -38,9 +38,9 @@ public abstract class TeamMiniGame extends MiniGame private final ArrayList _teams; - public TeamMiniGame(GameManager manager, String gameName) + public TeamMiniGame(GameManager manager, String map, String gameName) { - super(manager, gameName); + super(manager, map, gameName); this._teams = new ArrayList(); } diff --git a/src/main/java/moe/sdg/PluginSDG/commands/SDGCommand.java b/src/main/java/moe/sdg/PluginSDG/commands/SDGCommand.java index a6844aa..7359b1c 100644 --- a/src/main/java/moe/sdg/PluginSDG/commands/SDGCommand.java +++ b/src/main/java/moe/sdg/PluginSDG/commands/SDGCommand.java @@ -8,17 +8,19 @@ import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.Operations; +import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.io.Closer; import moe.sdg.PluginSDG.GameManager; import moe.sdg.PluginSDG.GameType; import moe.sdg.PluginSDG.MiniGame; +import moe.sdg.PluginSDG.exceptions.MapException; import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; - import java.awt.*; import java.io.BufferedOutputStream; import java.io.File; @@ -92,28 +94,48 @@ public class SDGCommand implements CommandExecutor return; } + GameType type = GameType.None; switch (args[1].toLowerCase()) { case "deathmatch": - if (args.length == 3) - { - _gameManager.createGame(GameType.DeathMatch, args[2]); - commandSender.sendMessage(ChatColor.BLUE + "Created deathmatch game with a default name since no name where precised"); - } - else - { - if (_gameManager.getGameByName(args[3]) != null) - commandSender.sendMessage(ChatColor.BLUE + "Name is already used" + args[0]); - else - { - _gameManager.createGame(GameType.DeathMatch, args[2], args[3]); - commandSender.sendMessage(ChatColor.BLUE + "Created deathmatch game"); - } - } + type = GameType.DeathMatch; break; default: commandSender.sendMessage(ChatColor.BLUE + "Unknown game type " + args[1]); - break; + return; + } + + try + { + MiniGame game = null; + if (args.length == 3) + { + int i = 1; + String name = null; + while (name == null || _gameManager.getGameByName(name) != null) + name = commandSender.getName() + "#" + i++; + game = _gameManager.createGame(type, args[2], name); + commandSender.sendMessage(ChatColor.BLUE + "Created deathmatch game with a default name since no name where precised"); + } + else + { + if (args[3].contains(" ")) + commandSender.sendMessage(ChatColor.BLUE + "A game can't have a space in it's name."); + else if (_gameManager.getGameByName(args[3]) != null) + commandSender.sendMessage(ChatColor.BLUE + "Name is already used" + args[0]); + else + { + game = _gameManager.createGame(type, args[2], args[3]); + commandSender.sendMessage(ChatColor.BLUE + "Created deathmatch game"); + } + } + + if (commandSender instanceof Player && game != null) + game.join((Player)commandSender); + } + catch (MapException e) + { + commandSender.sendMessage(e.toString()); } } @@ -240,14 +262,21 @@ public class SDGCommand implements CommandExecutor { Region region = session.getSelection(wePlayer.getWorld()); Clipboard cb = new BlockArrayClipboard(region); + cb.setOrigin(session.getPlacementPosition(wePlayer)); ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, cb, region.getMinimumPoint()); + copy.setCopyingEntities(true); + copy.setCopyingBiomes(true); Operations.complete(copy); LocalConfiguration config = this._worldEdit.getWorldEdit().getConfiguration(); File dir = new File(this._gameManager.getDataFolder(), args[1]); if (!dir.exists() && !dir.mkdirs()) throw new IOException("Could not create directory " + config.saveDir); File schematicFile = new File(dir, args[2] + ".schematic"); - schematicFile.createNewFile(); + if (!schematicFile.createNewFile()) + { + player.sendMessage("A map with the same name already exists."); + return; + } FileOutputStream fos = closer.register(new FileOutputStream(schematicFile)); BufferedOutputStream bos = closer.register(new BufferedOutputStream(fos)); @@ -267,6 +296,6 @@ public class SDGCommand implements CommandExecutor } catch (IOException ignore) { } } - player.sendMessage(Color.BLUE + "Map saved successfully."); + player.sendMessage(ChatColor.BLUE + "Map saved successfully."); } } diff --git a/src/main/java/moe/sdg/PluginSDG/exceptions/InvalidMapException.java b/src/main/java/moe/sdg/PluginSDG/exceptions/InvalidMapException.java new file mode 100644 index 0000000..4c22d9b --- /dev/null +++ b/src/main/java/moe/sdg/PluginSDG/exceptions/InvalidMapException.java @@ -0,0 +1,10 @@ +package moe.sdg.PluginSDG.exceptions; + +public class InvalidMapException extends MapException +{ + @Override + public String toString() + { + return "The specified map is invalid or corrupted and couldn't be loaded."; + } +} diff --git a/src/main/java/moe/sdg/PluginSDG/exceptions/MapException.java b/src/main/java/moe/sdg/PluginSDG/exceptions/MapException.java new file mode 100644 index 0000000..1359c19 --- /dev/null +++ b/src/main/java/moe/sdg/PluginSDG/exceptions/MapException.java @@ -0,0 +1,3 @@ +package moe.sdg.PluginSDG.exceptions; + +public class MapException extends RuntimeException { } diff --git a/src/main/java/moe/sdg/PluginSDG/exceptions/MapNotFoundException.java b/src/main/java/moe/sdg/PluginSDG/exceptions/MapNotFoundException.java new file mode 100644 index 0000000..5d1ebd9 --- /dev/null +++ b/src/main/java/moe/sdg/PluginSDG/exceptions/MapNotFoundException.java @@ -0,0 +1,10 @@ +package moe.sdg.PluginSDG.exceptions; + +public class MapNotFoundException extends MapException +{ + @Override + public String toString() + { + return "The specified map couldn't be found."; + } +} diff --git a/src/main/java/moe/sdg/PluginSDG/games/DeathMatch.java b/src/main/java/moe/sdg/PluginSDG/games/DeathMatch.java index c4d04a5..3894944 100644 --- a/src/main/java/moe/sdg/PluginSDG/games/DeathMatch.java +++ b/src/main/java/moe/sdg/PluginSDG/games/DeathMatch.java @@ -11,7 +11,7 @@ public class DeathMatch extends MiniGame public DeathMatch(GameManager gameManager, String map, String name) { - super(gameManager, name); + super(gameManager, map, name); } @Override