diff --git a/src/main/java/rip/tilly/bedwars/BedWars.java b/src/main/java/rip/tilly/bedwars/BedWars.java index 04acf41..3975ca2 100644 --- a/src/main/java/rip/tilly/bedwars/BedWars.java +++ b/src/main/java/rip/tilly/bedwars/BedWars.java @@ -1,7 +1,5 @@ package rip.tilly.bedwars; -import assemble.Assemble; -import assemble.AssembleStyle; import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.Chunk; @@ -9,12 +7,22 @@ import org.bukkit.World; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.plugin.java.JavaPlugin; +import rip.tilly.bedwars.listeners.InteractListener; +import rip.tilly.bedwars.listeners.PlayerDataListener; import rip.tilly.bedwars.listeners.RandomListeners; -import rip.tilly.bedwars.managers.ScoreboardManager; -import rip.tilly.bedwars.mongo.MongoManager; -import rip.tilly.bedwars.player.PlayerDataHandler; -import rip.tilly.bedwars.player.PlayerDataManager; +import rip.tilly.bedwars.managers.CommandManager; +import rip.tilly.bedwars.managers.GameManager; +import rip.tilly.bedwars.managers.PlayerDataManager; +import rip.tilly.bedwars.managers.SpawnManager; +import rip.tilly.bedwars.managers.arena.ArenaManager; +import rip.tilly.bedwars.managers.arena.chunk.ChunkClearingManager; +import rip.tilly.bedwars.managers.arena.chunk.ChunkManager; +import rip.tilly.bedwars.managers.hotbar.HotbarManager; +import rip.tilly.bedwars.managers.mongo.MongoManager; +import rip.tilly.bedwars.providers.scoreboard.ScoreboardProvider; import rip.tilly.bedwars.utils.CC; +import rip.tilly.bedwars.utils.assemble.Assemble; +import rip.tilly.bedwars.utils.assemble.AssembleStyle; import rip.tilly.bedwars.utils.config.file.Config; import java.util.Arrays; @@ -31,7 +39,14 @@ public final class BedWars extends JavaPlugin { private Config mainConfig, arenasConfig; private MongoManager mongoManager; + private ChunkClearingManager chunkClearingManager; private PlayerDataManager playerDataManager; + private SpawnManager spawnManager; + private ArenaManager arenaManager; + private ChunkManager chunkManager; + private HotbarManager hotbarManager; + private CommandManager commandManager; + private GameManager gameManager; @Override public void onEnable() { @@ -48,7 +63,7 @@ public final class BedWars extends JavaPlugin { this.loadManagers(); this.loadListeners(); - Assemble assemble = new Assemble(this, new ScoreboardManager()); + Assemble assemble = new Assemble(this, new ScoreboardProvider()); assemble.setTicks(2); assemble.setAssembleStyle(AssembleStyle.VIPER); @@ -58,6 +73,7 @@ public final class BedWars extends JavaPlugin { entity.remove(); } } + world.setGameRuleValue("doDaylightCycle", "false"); world.setTime(0L); world.setStorm(false); @@ -84,13 +100,19 @@ public final class BedWars extends JavaPlugin { private void loadManagers() { this.mongoManager = new MongoManager(); + this.chunkClearingManager = new ChunkClearingManager(); this.playerDataManager = new PlayerDataManager(); + this.spawnManager = new SpawnManager(); + this.arenaManager = new ArenaManager(); + this.chunkManager = new ChunkManager(); + this.hotbarManager = new HotbarManager(); + this.commandManager = new CommandManager(); + this.gameManager = new GameManager(); } private void loadListeners() { Arrays.asList( - new PlayerDataHandler(), - new RandomListeners() + new PlayerDataListener(), new RandomListeners(), new InteractListener() ).forEach(listener -> this.getServer().getPluginManager().registerEvents(listener, this)); } } diff --git a/src/main/java/rip/tilly/bedwars/commands/setspawn/MaxCommand.java b/src/main/java/rip/tilly/bedwars/commands/setspawn/MaxCommand.java new file mode 100644 index 0000000..b430c1a --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/commands/setspawn/MaxCommand.java @@ -0,0 +1,39 @@ +package rip.tilly.bedwars.commands.setspawn; + +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; +import rip.tilly.bedwars.BedWars; +import rip.tilly.bedwars.commands.BaseCommand; +import rip.tilly.bedwars.utils.CustomLocation; + +import java.util.ArrayList; +import java.util.List; + +public class MaxCommand extends BaseCommand { + + private BedWars main = BedWars.getInstance(); + + @Override + public void executeAs(CommandSender sender, Command cmd, String label, String[] args) { + Player player = (Player) sender; + this.main.getSpawnManager().setSpawnLocation(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(ChatColor.GREEN + "Successfully set the spawn min location."); + saveLocation(player, "SPAWN.MAX"); + } + + @Override + public List getTabCompletions(CommandSender sender, Command cmd, String label, String[] args) { + List tabCompletions = new ArrayList<>(); + + return tabCompletions; + } + + private void saveLocation(Player player, String location) { + FileConfiguration config = this.main.getMainConfig().getConfig(); + config.set(location, CustomLocation.locationToString(CustomLocation.fromBukkitLocation(player.getLocation()))); + this.main.getMainConfig().save(); + } +} diff --git a/src/main/java/rip/tilly/bedwars/commands/setspawn/MinCommand.java b/src/main/java/rip/tilly/bedwars/commands/setspawn/MinCommand.java new file mode 100644 index 0000000..32d7356 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/commands/setspawn/MinCommand.java @@ -0,0 +1,39 @@ +package rip.tilly.bedwars.commands.setspawn; + +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; +import rip.tilly.bedwars.BedWars; +import rip.tilly.bedwars.commands.BaseCommand; +import rip.tilly.bedwars.utils.CustomLocation; + +import java.util.ArrayList; +import java.util.List; + +public class MinCommand extends BaseCommand { + + private BedWars main = BedWars.getInstance(); + + @Override + public void executeAs(CommandSender sender, Command cmd, String label, String[] args) { + Player player = (Player) sender; + this.main.getSpawnManager().setSpawnLocation(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(ChatColor.GREEN + "Successfully set the spawn min location."); + saveLocation(player, "SPAWN.MIN"); + } + + @Override + public List getTabCompletions(CommandSender sender, Command cmd, String label, String[] args) { + List tabCompletions = new ArrayList<>(); + + return tabCompletions; + } + + private void saveLocation(Player player, String location) { + FileConfiguration config = this.main.getMainConfig().getConfig(); + config.set(location, CustomLocation.locationToString(CustomLocation.fromBukkitLocation(player.getLocation()))); + this.main.getMainConfig().save(); + } +} diff --git a/src/main/java/rip/tilly/bedwars/commands/setspawn/SetSpawnCommand.java b/src/main/java/rip/tilly/bedwars/commands/setspawn/SetSpawnCommand.java index 875414b..7258367 100644 --- a/src/main/java/rip/tilly/bedwars/commands/setspawn/SetSpawnCommand.java +++ b/src/main/java/rip/tilly/bedwars/commands/setspawn/SetSpawnCommand.java @@ -4,35 +4,39 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import rip.tilly.bedwars.BedWars; import rip.tilly.bedwars.utils.CC; public class SetSpawnCommand implements CommandExecutor { - private BedWars main = BedWars.getInstance(); - public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { Player player = (Player) sender; if (!player.hasPermission("bedwars.admin")) { player.sendMessage(CC.translate("&cNo permission")); - return true; } if (args.length == 0) { player.sendMessage(CC.translate("&cUsage:")); player.sendMessage(CC.translate(" &c/setspawn spawn")); + player.sendMessage(CC.translate(" &c/setspawn spawnmin")); + player.sendMessage(CC.translate(" &c/setspawn spawnmax")); player.sendMessage(CC.translate(" &c/setspawn holograms")); - } else { - switch (args[0]) { - case "spawn": - new SpawnCommand().executeAs(sender, cmd, label, args); + return true; + } - break; - case "holograms": - break; - } + switch (args[0].toLowerCase()) { + case "spawn": + new SpawnCommand().executeAs(sender, cmd, label, args); + break; + case "spawnmin": + new MinCommand().executeAs(sender, cmd, label, args); + break; + case "spawnmax": + new MaxCommand().executeAs(sender, cmd, label, args); + break; + case "holograms": + break; } return true; diff --git a/src/main/java/rip/tilly/bedwars/commands/setspawn/SpawnCommand.java b/src/main/java/rip/tilly/bedwars/commands/setspawn/SpawnCommand.java index 2f31ef8..5692b5c 100644 --- a/src/main/java/rip/tilly/bedwars/commands/setspawn/SpawnCommand.java +++ b/src/main/java/rip/tilly/bedwars/commands/setspawn/SpawnCommand.java @@ -1,12 +1,13 @@ package rip.tilly.bedwars.commands.setspawn; -import org.bukkit.Location; +import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import rip.tilly.bedwars.BedWars; import rip.tilly.bedwars.commands.BaseCommand; -import rip.tilly.bedwars.utils.CC; +import rip.tilly.bedwars.utils.CustomLocation; import java.util.ArrayList; import java.util.List; @@ -18,22 +19,21 @@ public class SpawnCommand extends BaseCommand { @Override public void executeAs(CommandSender sender, Command cmd, String label, String[] args) { Player player = (Player) sender; - - Location location = player.getLocation(); - - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); - - player.getWorld().setSpawnLocation(x, y, z); - - player.sendMessage(CC.translate("&aSpawn point set")); + this.main.getSpawnManager().setSpawnLocation(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(ChatColor.GREEN + "Successfully set the spawn location."); + saveLocation(player, "SPAWN.LOCATION"); } @Override public List getTabCompletions(CommandSender sender, Command cmd, String label, String[] args) { - List tabCompletions = new ArrayList(); + List tabCompletions = new ArrayList<>(); return tabCompletions; } + + private void saveLocation(Player player, String location) { + FileConfiguration config = this.main.getMainConfig().getConfig(); + config.set(location, CustomLocation.locationToString(CustomLocation.fromBukkitLocation(player.getLocation()))); + this.main.getMainConfig().save(); + } } diff --git a/src/main/java/rip/tilly/bedwars/game/Game.java b/src/main/java/rip/tilly/bedwars/game/Game.java index 37f4d6c..e969c7e 100644 --- a/src/main/java/rip/tilly/bedwars/game/Game.java +++ b/src/main/java/rip/tilly/bedwars/game/Game.java @@ -1,10 +1,21 @@ package rip.tilly.bedwars.game; +import io.netty.util.internal.ConcurrentSet; import lombok.Getter; import lombok.Setter; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.entity.Entity; +import org.github.paperspigot.Title; +import rip.tilly.bedwars.BedWars; +import rip.tilly.bedwars.game.arena.Arena; +import rip.tilly.bedwars.game.arena.CopiedArena; +import rip.tilly.bedwars.utils.CC; +import rip.tilly.bedwars.utils.TimeUtils; import java.util.Arrays; import java.util.List; +import java.util.Set; import java.util.UUID; /** @@ -15,10 +26,138 @@ import java.util.UUID; @Setter public class Game { - private final UUID gameId = UUID.randomUUID(); - private final List teams; + private final BedWars plugin = BedWars.getInstance(); - public Game(GameTeam... teams) { + private final Set entitiesToRemove = new ConcurrentSet<>(); + + private final List teams; + private final Arena arena; + + private final UUID gameId = UUID.randomUUID(); + + private CopiedArena copiedArena; + private GameState gameState = GameState.STARTING; + private int countdown = 6; + private int durationTimer; + + public Game(Arena arena, GameTeam... teams) { + this.arena = arena; this.teams = Arrays.asList(teams); } + + public GameTeam getTeamByName(String name) { + return this.teams.stream().filter(team -> team.getPlayerTeam().getName().equalsIgnoreCase(name)).findFirst().orElse(null); + } + + public String getDuration() { + return TimeUtils.formatIntoMMSS(durationTimer); + } + + public void addEntityToRemove(Entity entity) { + this.entitiesToRemove.add(entity); + } + + public void removeEntityToRemove(Entity entity) { + this.entitiesToRemove.remove(entity); + } + + public void clearEntitiesToRemove() { + this.entitiesToRemove.clear(); + } + + public void broadcastTitle(String message, String subMessage) { + Title title = new Title(message, subMessage, 5, 20, 5); + this.teams.forEach(team -> team.playingPlayers().forEach(player -> player.sendTitle(title))); + } + + public void broadcast(String message) { + this.teams.forEach(team -> team.playingPlayers().forEach(player -> player.sendMessage(CC.translate(message)))); + } + + public void broadcastSound(Sound sound) { + this.teams.forEach(team -> team.playingPlayers().forEach(player -> player.playSound(player.getLocation(), sound, 10, 1))); + } + + public int decrementCountdown() { + return --this.countdown; + } + + public void incrementDuration() { + ++this.durationTimer; + } + + public boolean isPartyMatch() { + return (this.teams.get(0).getAllPlayers().size() >= 2 || this.teams.get(1).getAllPlayers().size() >= 2); + } + + public boolean isPlaceable(Location location, Game game) { + double minX = game.getCopiedArena().getMin().getX(); + double minZ = game.getCopiedArena().getMin().getZ(); + double maxX = game.getCopiedArena().getMax().getX(); + double maxZ = game.getCopiedArena().getMax().getZ(); + + if (minX > maxX) { + double lastMinX = minX; + minX = maxX; + maxX = lastMinX; + } + + if (minZ > maxZ) { + double lastMinZ = minZ; + minZ = maxZ; + maxZ = lastMinZ; + } + + if (location.getX() >= minX && location.getX() <= maxX && location.getZ() >= minZ && location.getZ() <= maxZ) { + return true; + } + + return false; + } + + public boolean isInside(Location location, Game game) { + double aMinX = game.getCopiedArena().getTeamAmin().getX(); + double aMinZ = game.getCopiedArena().getTeamAmin().getZ(); + double aMaxX = game.getCopiedArena().getTeamAmax().getX(); + double aMaxZ = game.getCopiedArena().getTeamAmax().getZ(); + + if (aMinX > aMaxX) { + double lastMinX = aMinX; + aMinX = aMaxX; + aMaxX = lastMinX; + } + + if (aMinZ > aMaxZ) { + double lastMinZ = aMinZ; + aMinZ = aMaxZ; + aMaxZ = lastMinZ; + } + + if (location.getX() <= aMinX && location.getX() >= aMaxX && location.getZ() <= aMinZ && location.getZ() >= aMaxZ) { + return true; + } + + double bMinX = game.getCopiedArena().getTeamBmin().getX(); + double bMinZ = game.getCopiedArena().getTeamBmin().getZ(); + double bMaxX = game.getCopiedArena().getTeamBmax().getX(); + double bMaxZ = game.getCopiedArena().getTeamBmax().getZ(); + + if (bMinX > bMaxX) { + double lastMinX = bMinX; + bMinX = bMaxX; + bMaxX = lastMinX; + } + + if (bMinZ > bMaxZ) { + double lastMinZ = bMinZ; + bMinZ = bMaxZ; + bMaxZ = lastMinZ; + } + + if (location.getX() <= bMinX && location.getX() >= bMaxX && location.getZ() <= bMinZ && location.getZ() >= bMaxZ) { + return true; + } + + return false; + } } diff --git a/src/main/java/rip/tilly/bedwars/game/GameRequest.java b/src/main/java/rip/tilly/bedwars/game/GameRequest.java new file mode 100644 index 0000000..2e217c5 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/game/GameRequest.java @@ -0,0 +1,18 @@ +package rip.tilly.bedwars.game; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import rip.tilly.bedwars.game.arena.Arena; + +import java.util.UUID; + +@Getter +@RequiredArgsConstructor +public class GameRequest { + + private final UUID requester; + private final UUID requested; + + private final Arena arena; + private final boolean party; +} diff --git a/src/main/java/rip/tilly/bedwars/game/GameState.java b/src/main/java/rip/tilly/bedwars/game/GameState.java new file mode 100644 index 0000000..f9ece9c --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/game/GameState.java @@ -0,0 +1,7 @@ +package rip.tilly.bedwars.game; + +public enum GameState { + STARTING, + FIGHTING, + ENDING +} diff --git a/src/main/java/rip/tilly/bedwars/game/GameTeam.java b/src/main/java/rip/tilly/bedwars/game/GameTeam.java index 5ee671d..a75be25 100644 --- a/src/main/java/rip/tilly/bedwars/game/GameTeam.java +++ b/src/main/java/rip/tilly/bedwars/game/GameTeam.java @@ -26,17 +26,19 @@ public class GameTeam { private final List playingPlayers = new ArrayList<>(); private UUID leader; + private final int id; private final PlayerTeam playerTeam; - public GameTeam(UUID leader, List allPlayers, PlayerTeam playerTeam) { + public GameTeam(UUID leader, List allPlayers, int id, PlayerTeam playerTeam) { this.leader = leader; this.allPlayers = allPlayers; this.playingPlayers.addAll(allPlayers); + this.id = id; this.playerTeam = playerTeam; } - public void removePlayer(UUID uuid) { + public void killPlayer(UUID uuid) { this.playingPlayers.remove(uuid); } diff --git a/src/main/java/rip/tilly/bedwars/game/events/GameEndEvent.java b/src/main/java/rip/tilly/bedwars/game/events/GameEndEvent.java new file mode 100644 index 0000000..106c9f6 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/game/events/GameEndEvent.java @@ -0,0 +1,19 @@ +package rip.tilly.bedwars.game.events; + +import lombok.Getter; +import rip.tilly.bedwars.game.Game; +import rip.tilly.bedwars.game.GameTeam; + +@Getter +public class GameEndEvent extends GameEvent { + + private final GameTeam winningTeam; + private final GameTeam losingTeam; + + public GameEndEvent(Game game, GameTeam winningTeam, GameTeam losingTeam) { + super(game); + + this.winningTeam = winningTeam; + this.losingTeam = losingTeam; + } +} diff --git a/src/main/java/rip/tilly/bedwars/game/events/GameEvent.java b/src/main/java/rip/tilly/bedwars/game/events/GameEvent.java new file mode 100644 index 0000000..3d53489 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/game/events/GameEvent.java @@ -0,0 +1,24 @@ +package rip.tilly.bedwars.game.events; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import rip.tilly.bedwars.game.Game; + +@Getter +@RequiredArgsConstructor +public class GameEvent extends Event { + + private static final HandlerList HANDLERS = new HandlerList(); + private final Game game; + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + @Override + public HandlerList getHandlers() { + return HANDLERS; + } +} diff --git a/src/main/java/rip/tilly/bedwars/game/events/GameStartEvent.java b/src/main/java/rip/tilly/bedwars/game/events/GameStartEvent.java new file mode 100644 index 0000000..3569528 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/game/events/GameStartEvent.java @@ -0,0 +1,9 @@ +package rip.tilly.bedwars.game.events; + +import rip.tilly.bedwars.game.Game; + +public class GameStartEvent extends GameEvent { + public GameStartEvent(Game game) { + super(game); + } +} diff --git a/src/main/java/rip/tilly/bedwars/listeners/InteractListener.java b/src/main/java/rip/tilly/bedwars/listeners/InteractListener.java new file mode 100644 index 0000000..91a1930 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/listeners/InteractListener.java @@ -0,0 +1,120 @@ +package rip.tilly.bedwars.listeners; + +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.material.TrapDoor; +import rip.tilly.bedwars.BedWars; +import rip.tilly.bedwars.managers.hotbar.impl.HotbarItem; +import rip.tilly.bedwars.player.PlayerData; +import rip.tilly.bedwars.player.PlayerState; + +/** + * Created by Lucanius + * Project: BedWars + */ +public class InteractListener implements Listener { + + private final BedWars plugin = BedWars.getInstance(); + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if ((event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.RIGHT_CLICK_AIR)) { + return; + } + + Player player = event.getPlayer(); + if (player.getGameMode() == GameMode.CREATIVE) { + return; + } + + if (event.getAction().name().endsWith("_BLOCK")) { + if (event.getClickedBlock().getType().name().contains("FENCE") && (event.getClickedBlock().getState() instanceof TrapDoor) + || event.getClickedBlock().getType().name().contains("TRAP") || event.getClickedBlock().getType().name().contains("CHEST") + || event.getClickedBlock().getType().name().contains("DOOR") || event.getClickedBlock().getType().equals(Material.BEACON) + || event.getClickedBlock().getType().equals(Material.FURNACE) || event.getClickedBlock().getType().equals(Material.WORKBENCH) + || event.getClickedBlock().getType().equals(Material.NOTE_BLOCK) || event.getClickedBlock().getType().equals(Material.JUKEBOX) + || event.getClickedBlock().getType().equals(Material.ANVIL) || event.getClickedBlock().getType().equals(Material.HOPPER) + || event.getClickedBlock().getType().equals(Material.BED_BLOCK) || event.getClickedBlock().getType().equals(Material.DROPPER) + || event.getClickedBlock().getType().equals(Material.BREWING_STAND)) { + event.setCancelled(true); + return; + } + } + + ItemStack itemStack = player.getItemInHand(); + if (!event.hasItem() || itemStack == null) { + return; + } + + PlayerData playerData = this.plugin.getPlayerDataManager().getPlayerData(player.getUniqueId()); + if (playerData.getPlayerState() == PlayerState.PLAYING) { + return; + } + + HotbarItem hotbarItem = HotbarItem.getItemByItemStack(player.getItemInHand()); + if (hotbarItem == null) { + return; + } + + if (hotbarItem.getActionType() == null) { + return; + } + + event.setCancelled(true); + + switch (playerData.getPlayerState()) { + case SPAWN: + switch (hotbarItem.getActionType()) { + case QUEUE_MENU: + // open queue menu + break; + case SETTINGS_MENU: + // open settings menu + break; + case CREATE_PARTY: + // create party + break; + case COSMETICS_MENU: + // open cosmetics menu + break; + case PREFERENCES_MENU: + // open preferences menu + break; + + case PARTY_GAMES: + // open party games menu + break; + case PARTY_INFO: + // show party info + break; + case PARTY_LEAVE: + // leave party + break; + } + break; + case QUEUE: + switch (hotbarItem.getActionType()) { + case LEAVE_QUEUE: + // leave queue + break; + } + break; + case SPECTATING: + switch (hotbarItem.getActionType()) { + case SPECTATOR_MENU: + // open player tracker menu + break; + case SPECTATOR_LEAVE: + // leave spectator mode + break; + } + break; + } + } +} diff --git a/src/main/java/rip/tilly/bedwars/player/PlayerDataHandler.java b/src/main/java/rip/tilly/bedwars/listeners/PlayerDataListener.java similarity index 92% rename from src/main/java/rip/tilly/bedwars/player/PlayerDataHandler.java rename to src/main/java/rip/tilly/bedwars/listeners/PlayerDataListener.java index dada6b5..46a1ce6 100644 --- a/src/main/java/rip/tilly/bedwars/player/PlayerDataHandler.java +++ b/src/main/java/rip/tilly/bedwars/listeners/PlayerDataListener.java @@ -1,4 +1,4 @@ -package rip.tilly.bedwars.player; +package rip.tilly.bedwars.listeners; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -7,12 +7,13 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.*; import rip.tilly.bedwars.BedWars; +import rip.tilly.bedwars.player.PlayerData; /** * Created by Lucanius * Project: BedWars */ -public class PlayerDataHandler implements Listener { +public class PlayerDataListener implements Listener { private final BedWars plugin = BedWars.getInstance(); @@ -72,6 +73,7 @@ public class PlayerDataHandler implements Listener { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { event.setJoinMessage(null); + this.plugin.getPlayerDataManager().resetPlayer(event.getPlayer(), true); } private void handleDataSave(PlayerData playerData) { diff --git a/src/main/java/rip/tilly/bedwars/listeners/RandomListeners.java b/src/main/java/rip/tilly/bedwars/listeners/RandomListeners.java index 63e728d..18315c8 100644 --- a/src/main/java/rip/tilly/bedwars/listeners/RandomListeners.java +++ b/src/main/java/rip/tilly/bedwars/listeners/RandomListeners.java @@ -2,12 +2,18 @@ package rip.tilly.bedwars.listeners; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockFadeEvent; import org.bukkit.event.entity.FoodLevelChangeEvent; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.weather.WeatherChangeEvent; +import rip.tilly.bedwars.BedWars; +import rip.tilly.bedwars.player.PlayerData; +import rip.tilly.bedwars.player.PlayerState; public class RandomListeners implements Listener { + private final BedWars plugin = BedWars.getInstance(); + @EventHandler public void onFoodLevelChange(FoodLevelChangeEvent event) { event.setCancelled(true); @@ -15,14 +21,19 @@ public class RandomListeners implements Listener { @EventHandler public void onPlayerDropItem(PlayerDropItemEvent event) { - // event.setCancelled(true); - - // to do - // only be able to drop an item when the player is in a game + PlayerData playerData = this.plugin.getPlayerDataManager().getPlayerData(event.getPlayer().getUniqueId()); + if (playerData.getPlayerState() != PlayerState.PLAYING) { + event.setCancelled(true); + } } @EventHandler public void onWeatherChange(WeatherChangeEvent event) { event.setCancelled(true); } + + @EventHandler + public void onBlockFade(BlockFadeEvent event) { + event.setCancelled(true); + } } diff --git a/src/main/java/rip/tilly/bedwars/managers/ArenaManager.java b/src/main/java/rip/tilly/bedwars/managers/ArenaManager.java deleted file mode 100644 index 43303f2..0000000 --- a/src/main/java/rip/tilly/bedwars/managers/ArenaManager.java +++ /dev/null @@ -1,55 +0,0 @@ -package rip.tilly.bedwars.managers; - -import lombok.Getter; -import lombok.Setter; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; -import rip.tilly.bedwars.BedWars; -import rip.tilly.bedwars.game.arena.Arena; -import rip.tilly.bedwars.game.arena.CopiedArena; -import rip.tilly.bedwars.utils.config.file.Config; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -public class ArenaManager { - - private final BedWars plugin = BedWars.getInstance(); - private final Config config = this.plugin.getArenasConfig(); - - @Getter private final Map arenas = new HashMap<>(); - @Getter private final Map arenaMatchUUIDs = new HashMap<>(); - - @Getter @Setter private int generatingArenaRunnable; - - public ArenaManager() { - - } - - private void loadArenas() { - FileConfiguration fileConfig = config.getConfig(); - ConfigurationSection section = fileConfig.getConfigurationSection("arenas"); - if (section == null) { - return; - } - - section.getKeys(false).forEach(name -> { - String icon = section.getString(name + ".icon") == null ? Material.PAPER.name() : section.getString(name + ".icon"); - int iconData = section.getInt(name + ".icon-data"); - - String a = section.getString(name + ".a"); - String b = section.getString(name + ".b"); - String min = section.getString(name + ".min"); - String max = section.getString(name + ".max"); - String teamAmin = section.getString(name + ".teamAmin"); - String teamAmax = section.getString(name + ".teamAmax"); - String teamBmin = section.getString(name + ".teamBmin"); - String teamBmax = section.getString(name + ".teamBmax"); - - int deadZone = section.getInt(name + ".deadZone"); - int buildMax = section.getInt(name + ".buildMax"); - }); - } -} diff --git a/src/main/java/rip/tilly/bedwars/managers/GameManager.java b/src/main/java/rip/tilly/bedwars/managers/GameManager.java new file mode 100644 index 0000000..b1d5fc2 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/managers/GameManager.java @@ -0,0 +1,96 @@ +package rip.tilly.bedwars.managers; + +import lombok.Getter; +import org.bukkit.entity.Player; +import rip.tilly.bedwars.BedWars; +import rip.tilly.bedwars.game.Game; +import rip.tilly.bedwars.game.GameRequest; +import rip.tilly.bedwars.game.GameTeam; +import rip.tilly.bedwars.game.arena.Arena; +import rip.tilly.bedwars.game.events.GameEndEvent; +import rip.tilly.bedwars.game.events.GameStartEvent; +import rip.tilly.bedwars.player.PlayerData; +import rip.tilly.bedwars.utils.TtlHashMap; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +/** + * Created by Lucanius + * Project: BedWars + */ +public class GameManager { + + private final BedWars plugin = BedWars.getInstance(); + + private final Map> gameRequests = new TtlHashMap<>(TimeUnit.SECONDS, 30); + @Getter private final Map games = new ConcurrentHashMap<>(); + + public Game getGame(PlayerData playerData) { + return this.games.get(playerData.getCurrentGameId()); + } + + public Game getGame(UUID uuid) { + return this.getGame(this.plugin.getPlayerDataManager().getPlayerData(uuid)); + } + + public Game getGameFromUUID(UUID uuid) { + return this.games.get(uuid); + } + + public void createGameRequest(Player requester, Player requested, Arena arena, boolean party) { + GameRequest request = new GameRequest(requester.getUniqueId(), requested.getUniqueId(), arena, party); + this.gameRequests.computeIfAbsent(requested.getUniqueId(), k -> new HashSet<>()).add(request); + } + + public GameRequest getGameRequest(UUID requester, UUID requested) { + Set requests = this.gameRequests.get(requested); + if (requests == null) { + return null; + } + + return requests.stream().filter(req -> req.getRequester().equals(requester)).findAny().orElse(null); + } + + public void removeGameRequests(UUID uuid) { + this.gameRequests.remove(uuid); + } + + public void createGame(Game game) { + this.games.put(game.getGameId(), game); + this.plugin.getServer().getPluginManager().callEvent(new GameStartEvent(game)); + } + + public void removeGame(Game game) { + this.games.remove(game.getGameId()); + } + + public void removePlayerFromGame(Player player, PlayerData playerData) { + Game game = this.games.get(playerData.getCurrentGameId()); + Player killer = player.getKiller(); + + if (player.isOnline() && killer != null) { + killer.hidePlayer(player); + } + + GameTeam losingTeam = game.getTeams().get(playerData.getTeamId()); + GameTeam winningTeam = game.getTeams().get(losingTeam.getId() == 0 ? 1 : 0); + + if (killer != null) { + game.broadcast(losingTeam.getPlayerTeam().getChatColor() + player.getName() + " &ehas been killed by " + winningTeam.getPlayerTeam().getChatColor() + killer.getName() + "&e! &b&lFINAL KILL!"); + } else { + game.broadcast(losingTeam.getPlayerTeam().getChatColor() + player.getName() + " &ehas died! &b&lFINAL KILL!"); + } + + losingTeam.killPlayer(player.getUniqueId()); + int remaining = losingTeam.getPlayingPlayers().size(); + + if (remaining == 0) { + this.plugin.getServer().getPluginManager().callEvent(new GameEndEvent(game, winningTeam, losingTeam)); + } + } +} diff --git a/src/main/java/rip/tilly/bedwars/player/PlayerDataManager.java b/src/main/java/rip/tilly/bedwars/managers/PlayerDataManager.java similarity index 69% rename from src/main/java/rip/tilly/bedwars/player/PlayerDataManager.java rename to src/main/java/rip/tilly/bedwars/managers/PlayerDataManager.java index f997f29..0e92a26 100644 --- a/src/main/java/rip/tilly/bedwars/player/PlayerDataManager.java +++ b/src/main/java/rip/tilly/bedwars/managers/PlayerDataManager.java @@ -1,11 +1,16 @@ -package rip.tilly.bedwars.player; +package rip.tilly.bedwars.managers; import com.mongodb.client.MongoCursor; import com.mongodb.client.model.Filters; import com.mongodb.client.model.UpdateOptions; import lombok.Getter; import org.bson.Document; +import org.bukkit.entity.Player; import rip.tilly.bedwars.BedWars; +import rip.tilly.bedwars.managers.hotbar.impl.HotbarItem; +import rip.tilly.bedwars.player.PlayerData; +import rip.tilly.bedwars.player.PlayerState; +import rip.tilly.bedwars.utils.PlayerUtil; import java.util.Collection; import java.util.HashMap; @@ -77,4 +82,29 @@ public class PlayerDataManager { return this.plugin.getMongoManager().getPlayers().find().sort(document).limit(limit).iterator(); } + + public void resetPlayer(Player player, boolean toSpawn) { + PlayerData playerData = this.getPlayerData(player.getUniqueId()); + playerData.setPlayerState(PlayerState.SPAWN); + + PlayerUtil.clearPlayer(player); + + this.giveSpawnItems(player); + + if (toSpawn) { + player.teleport(this.plugin.getSpawnManager().getSpawnLocation().toBukkitLocation()); + } + } + + public void giveSpawnItems(Player player) { + boolean inParty = false; // check if the player is in a party + + if (inParty) { + this.plugin.getHotbarManager().getPartyItems().stream().filter(HotbarItem::isEnabled).forEach(item -> player.getInventory().setItem(item.getSlot(), item.getItemStack())); + } else { + this.plugin.getHotbarManager().getSpawnItems().stream().filter(HotbarItem::isEnabled).forEach(item -> player.getInventory().setItem(item.getSlot(), item.getItemStack())); + } + + player.updateInventory(); + } } diff --git a/src/main/java/rip/tilly/bedwars/managers/ScoreboardManager.java b/src/main/java/rip/tilly/bedwars/managers/ScoreboardManager.java deleted file mode 100644 index 0c3a32d..0000000 --- a/src/main/java/rip/tilly/bedwars/managers/ScoreboardManager.java +++ /dev/null @@ -1,62 +0,0 @@ -package rip.tilly.bedwars.managers; - -import assemble.AssembleAdapter; -import org.bukkit.entity.Player; -import rip.tilly.bedwars.BedWars; -import rip.tilly.bedwars.player.PlayerData; -import rip.tilly.bedwars.utils.CC; - -import java.util.ArrayList; -import java.util.List; - -public class ScoreboardManager implements AssembleAdapter { - - private BedWars main = BedWars.getInstance(); - - @Override - public String getTitle(Player player) { - return CC.translate("&d&lBedWars"); - } - - @Override - public List getLines(Player player) { - List lines = new ArrayList(); - - PlayerData playerData = this.main.getPlayerDataManager().getPlayerData(player.getUniqueId()); - - lines.add(CC.translate(CC.scoreboardBar)); - lines.add(CC.translate("&fOnline: &d" + this.main.getServer().getOnlinePlayers().size())); - lines.add(CC.translate("&fPlaying: &d")); - lines.add(CC.translate("")); - - if (true) { - lines.add(CC.translate("&fLevel: &d" + playerData.getLevel())); - - String finishedProgress = ""; - - int notFinishedProgress = 10; - - for (int i = 0; i < playerData.getXp() * 100; i++) { - if (i % 10 == 0) { - finishedProgress += "⬛"; - - notFinishedProgress--; - } - } - - String leftOverProgress = ""; - - for (int i = 1; i <= notFinishedProgress; i++) { - leftOverProgress += "⬛"; - } - - lines.add(CC.translate("&8" + finishedProgress + "&7" + leftOverProgress + " &7(" + ((int) (playerData.getXp() * 100)) + "%&7)")); - lines.add(CC.translate("")); - } - - lines.add(CC.translate("&dtilly.rip")); - lines.add(CC.translate(CC.scoreboardBar)); - - return lines; - } -} diff --git a/src/main/java/rip/tilly/bedwars/managers/SpawnManager.java b/src/main/java/rip/tilly/bedwars/managers/SpawnManager.java new file mode 100644 index 0000000..0cd5938 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/managers/SpawnManager.java @@ -0,0 +1,49 @@ +package rip.tilly.bedwars.managers; + +import lombok.Getter; +import lombok.Setter; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.FileConfiguration; +import rip.tilly.bedwars.BedWars; +import rip.tilly.bedwars.utils.CC; +import rip.tilly.bedwars.utils.CustomLocation; + +/** + * Created by Lucanius + * Project: BedWars + */ +@Getter +@Setter +public class SpawnManager { + + private final BedWars plugin = BedWars.getInstance(); + private final FileConfiguration config = this.plugin.getMainConfig().getConfig(); + + private CustomLocation spawnLocation; + private CustomLocation spawnMin; + private CustomLocation spawnMax; + + public SpawnManager() { + this.loadConfig(); + } + + private void loadConfig() { + if (this.config.contains("SPAWN.LOCATION")) { + try { + this.spawnLocation = CustomLocation.stringToLocation(this.config.getString("SPAWN.LOCATION")); + this.spawnMin = CustomLocation.stringToLocation(this.config.getString("SPAWN.MIN")); + this.spawnMax = CustomLocation.stringToLocation(this.config.getString("SPAWN.MAX")); + } catch (NullPointerException exception) { + Bukkit.getConsoleSender().sendMessage(CC.translate("&cSpawn min & max locations not found!")); + } + } + } + + public void saveConfig() { + this.config.set("SPAWN.LOCATION", CustomLocation.locationToString(this.spawnLocation)); + this.config.set("SPAWN.MIN", CustomLocation.locationToString(this.spawnMin)); + this.config.set("SPAWN.MAX", CustomLocation.locationToString(this.spawnMax)); + + this.plugin.getMainConfig().save(); + } +} diff --git a/src/main/java/rip/tilly/bedwars/managers/arena/ArenaManager.java b/src/main/java/rip/tilly/bedwars/managers/arena/ArenaManager.java new file mode 100644 index 0000000..719f930 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/managers/arena/ArenaManager.java @@ -0,0 +1,247 @@ +package rip.tilly.bedwars.managers.arena; + +import lombok.Getter; +import lombok.Setter; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import rip.tilly.bedwars.BedWars; +import rip.tilly.bedwars.game.arena.Arena; +import rip.tilly.bedwars.game.arena.CopiedArena; +import rip.tilly.bedwars.utils.CustomLocation; +import rip.tilly.bedwars.utils.config.file.Config; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; + +/** + * Created by Lucanius + * Project: BedWars + */ +public class ArenaManager { + + private final BedWars plugin = BedWars.getInstance(); + private final Config config = this.plugin.getArenasConfig(); + + @Getter private final Map arenas = new HashMap<>(); + @Getter private final Map arenaGameUUIDs = new HashMap<>(); + + @Getter @Setter private int generatingArenaRunnable; + + public ArenaManager() { + this.loadArenas(); + } + + private void loadArenas() { + FileConfiguration fileConfig = this.config.getConfig(); + ConfigurationSection section = fileConfig.getConfigurationSection("arenas"); + if (section == null) { + return; + } + + section.getKeys(false).forEach(name -> { + String icon = section.getString(name + ".icon") == null ? Material.PAPER.name() : section.getString(name + ".icon"); + int iconData = section.getInt(name + ".icon-data"); + + String a = section.getString(name + ".a"); + String b = section.getString(name + ".b"); + String min = section.getString(name + ".min"); + String max = section.getString(name + ".max"); + String teamAmin = section.getString(name + ".teamAmin"); + String teamAmax = section.getString(name + ".teamAmax"); + String teamBmin = section.getString(name + ".teamBmin"); + String teamBmax = section.getString(name + ".teamBmax"); + + int deadZone = section.getInt(name + ".deadZone"); + int buildMax = section.getInt(name + ".buildMax"); + + CustomLocation spawnA = CustomLocation.stringToLocation(a); + CustomLocation spawnB = CustomLocation.stringToLocation(b); + CustomLocation locMin = CustomLocation.stringToLocation(min); + CustomLocation locMax = CustomLocation.stringToLocation(max); + CustomLocation locTeamAmin = CustomLocation.stringToLocation(teamAmin); + CustomLocation locTeamAmax = CustomLocation.stringToLocation(teamAmax); + CustomLocation locTeamBmin = CustomLocation.stringToLocation(teamBmin); + CustomLocation locTeamBmax = CustomLocation.stringToLocation(teamBmax); + + List copiedArenas = new ArrayList<>(); + ConfigurationSection copiedSection = section.getConfigurationSection(name + ".copiedArenas"); + if (copiedSection != null) { + copiedSection.getKeys(false).forEach(copy -> { + String copyA = copiedSection.getString(copy + ".a"); + String copyB = copiedSection.getString(copy + ".b"); + String copyMin = copiedSection.getString(copy + ".min"); + String copyMax = copiedSection.getString(copy + ".max"); + String copyTeamAmin = copiedSection.getString(copy + ".teamAmin"); + String copyTeamAmax = copiedSection.getString(copy + ".teamAmax"); + String copyTeamBmin = copiedSection.getString(copy + ".teamBmin"); + String copyTeamBmax = copiedSection.getString(copy + ".teamBmax"); + + CustomLocation copySpawnA = CustomLocation.stringToLocation(copyA); + CustomLocation copySpawnB = CustomLocation.stringToLocation(copyB); + CustomLocation copyLocMin = CustomLocation.stringToLocation(copyMin); + CustomLocation copyLocMax = CustomLocation.stringToLocation(copyMax); + CustomLocation copyLocTeamAmin = CustomLocation.stringToLocation(copyTeamAmin); + CustomLocation copyLocTeamAmax = CustomLocation.stringToLocation(copyTeamAmax); + CustomLocation copyLocTeamBmin = CustomLocation.stringToLocation(copyTeamBmin); + CustomLocation copyLocTeamBmax = CustomLocation.stringToLocation(copyTeamBmax); + + CopiedArena copiedArena = new CopiedArena( + copySpawnA, + copySpawnB, + copyLocMin, + copyLocMax, + copyLocTeamAmin, + copyLocTeamAmax, + copyLocTeamBmin, + copyLocTeamBmax + ); + + this.plugin.getChunkClearingManager().copyArena(copiedArena); + + copiedArenas.add(copiedArena); + }); + } + + boolean enabled = section.getBoolean(name + ".enabled", false); + + Arena arena = new Arena( + name, + copiedArenas, + new ArrayList<>(copiedArenas), + icon, + iconData, + spawnA, + spawnB, + locMin, + locMax, + locTeamAmin, + locTeamAmax, + locTeamBmin, + locTeamBmax, + deadZone, + buildMax, + enabled + ); + + this.arenas.put(name, arena); + }); + } + + public void saveArenas() { + FileConfiguration fileConfig = this.config.getConfig(); + fileConfig.set("arenas", null); + arenas.forEach((name, arena) -> { + String icon = arena.getIcon(); + int iconData = arena.getIconData(); + + String a = CustomLocation.locationToString(arena.getA()); + String b = CustomLocation.locationToString(arena.getB()); + String min = CustomLocation.locationToString(arena.getMin()); + String max = CustomLocation.locationToString(arena.getMax()); + String teamAmin = CustomLocation.locationToString(arena.getTeamAmin()); + String teamAmax = CustomLocation.locationToString(arena.getTeamAmax()); + String teamBmin = CustomLocation.locationToString(arena.getTeamBmin()); + String teamBmax = CustomLocation.locationToString(arena.getTeamBmax()); + + int deadZone = arena.getDeadZone(); + int buildMax = arena.getBuildMax(); + + String root = "arenas." + name; + + fileConfig.set(root + ".icon", icon); + fileConfig.set(root + ".icon-data", iconData); + + fileConfig.set(root + ".a", a); + fileConfig.set(root + ".b", b); + fileConfig.set(root + ".min", min); + fileConfig.set(root + ".max", max); + fileConfig.set(root + ".teamAmin", teamAmin); + fileConfig.set(root + ".teamAmax", teamAmax); + fileConfig.set(root + ".teamBmin", teamBmin); + fileConfig.set(root + ".teamBmax", teamBmax); + + fileConfig.set(root + ".deadZone", deadZone); + fileConfig.set(root + ".buildMax", buildMax); + + fileConfig.set(root + ".enabled", arena.isEnabled()); + fileConfig.set(root + ".copiedArenas", null); + + int i = 0; + if (arena.getCopiedArenas() != null) { + for (CopiedArena copiedArena : arena.getCopiedArenas()) { + String copyA = CustomLocation.locationToString(copiedArena.getA()); + String copyB = CustomLocation.locationToString(copiedArena.getB()); + String copyMin = CustomLocation.locationToString(copiedArena.getMin()); + String copyMax = CustomLocation.locationToString(copiedArena.getMax()); + String copyTeamAmin = CustomLocation.locationToString(copiedArena.getTeamAmin()); + String copyTeamAmax = CustomLocation.locationToString(copiedArena.getTeamAmax()); + String copyTeamBmin = CustomLocation.locationToString(copiedArena.getTeamBmin()); + String copyTeamBmax = CustomLocation.locationToString(copiedArena.getTeamBmax()); + + String copyRoot = root + ".copiedArenas" + i; + + fileConfig.set(copyRoot + ".a", copyA); + fileConfig.set(copyRoot + ".b", copyB); + fileConfig.set(copyRoot + ".min", copyMin); + fileConfig.set(copyRoot + ".max", copyMax); + fileConfig.set(copyRoot + ".teamAmin", copyTeamAmin); + fileConfig.set(copyRoot + ".teamAmax", copyTeamAmax); + fileConfig.set(copyRoot + ".teamBmin", copyTeamBmin); + fileConfig.set(copyRoot + ".teamBmax", copyTeamBmax); + + i++; + } + } + }); + + this.config.save(); + } + + public void reloadArenas() { + this.saveArenas(); + this.arenas.clear(); + this.loadArenas(); + } + + public void createArena(String name) { + this.arenas.put(name, new Arena(name)); + } + + public void deleteArena(String name) { + this.arenas.remove(name); + } + + public Arena getArena(String name) { + return this.arenas.get(name); + } + + public Arena getRandomArena() { + List enabledArenas = new ArrayList<>(); + + for (Arena arena : this.arenas.values()) { + if (!arena.isEnabled()) { + continue; + } + enabledArenas.add(arena); + } + + if (enabledArenas.size() == 0) { + return null; + } + + return enabledArenas.get(ThreadLocalRandom.current().nextInt(enabledArenas.size())); + } + + public void removeArenaGameUUID(CopiedArena copiedArena) { + this.arenaGameUUIDs.remove(copiedArena); + } + + public UUID getArenaGameUUID(CopiedArena copiedArena) { + return this.arenaGameUUIDs.get(copiedArena); + } + + public void setArenaGameUUIDs(CopiedArena copiedArena, UUID uuid) { + this.arenaGameUUIDs.put(copiedArena, uuid); + } +} diff --git a/src/main/java/rip/tilly/bedwars/managers/arena/chunk/ChunkClearingManager.java b/src/main/java/rip/tilly/bedwars/managers/arena/chunk/ChunkClearingManager.java new file mode 100644 index 0000000..400e383 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/managers/arena/chunk/ChunkClearingManager.java @@ -0,0 +1,61 @@ +package rip.tilly.bedwars.managers.arena.chunk; + +import net.minecraft.server.v1_8_R3.Chunk; +import net.minecraft.server.v1_8_R3.ChunkSection; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_8_R3.CraftChunk; +import rip.tilly.bedwars.game.arena.CopiedArena; +import rip.tilly.bedwars.managers.arena.chunk.data.BedWarsChunk; +import rip.tilly.bedwars.managers.arena.chunk.data.BedWarsChunkData; +import rip.tilly.bedwars.managers.arena.chunk.data.BedWarsNMSUtil; +import rip.tilly.bedwars.utils.CC; +import rip.tilly.bedwars.utils.cuboid.Cuboid; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * This code has been created by + * gatogamer#6666 A.K.A. gatogamer. + * If you want to use my code, please + * don't remove this messages and + * give me the credits. Arigato! n.n + */ +public class ChunkClearingManager { + + public Map chunks = new ConcurrentHashMap<>(); + + public void copyArena(CopiedArena copiedArena) { + long time = System.currentTimeMillis(); + + Cuboid cuboid = new Cuboid(copiedArena.getMin().toBukkitLocation(), copiedArena.getMax().toBukkitLocation()); + BedWarsChunkData data = new BedWarsChunkData(); + + cuboid.getChunks().forEach(chunk -> { + chunk.load(); + Chunk nmsChunk = ((CraftChunk) chunk).getHandle(); + ChunkSection[] nmsSection = BedWarsNMSUtil.cloneSections(nmsChunk.getSections()); + data.chunks.put(new BedWarsChunk(chunk.getX(), chunk.getZ()), BedWarsNMSUtil.cloneSections(nmsSection)); + }); + + chunks.put(copiedArena, data); + + Bukkit.getConsoleSender().sendMessage(CC.translate("&aArena copied! &a&l(" + (System.currentTimeMillis() - time) + "ms)")); + } + + public void resetArena(CopiedArena copiedArena) { + long time = System.currentTimeMillis(); + + Cuboid cuboid = new Cuboid(copiedArena.getMin().toBukkitLocation(), copiedArena.getMax().toBukkitLocation()); + cuboid.getChunks().forEach(chunk -> { + try { + chunk.load(); + BedWarsNMSUtil.setSections(((CraftChunk) chunk).getHandle(), BedWarsNMSUtil.cloneSections(chunks.get(copiedArena).getBedWarsChunk(chunk.getX(), chunk.getZ()))); + } catch (Exception exception) { + exception.printStackTrace(); + } + }); + + Bukkit.getConsoleSender().sendMessage(CC.translate("&aArena reset! &a&l(" + (System.currentTimeMillis() - time) + "ms)")); + } +} diff --git a/src/main/java/rip/tilly/bedwars/managers/arena/chunk/ChunkManager.java b/src/main/java/rip/tilly/bedwars/managers/arena/chunk/ChunkManager.java new file mode 100644 index 0000000..40866f5 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/managers/arena/chunk/ChunkManager.java @@ -0,0 +1,118 @@ +package rip.tilly.bedwars.managers.arena.chunk; + +import org.bukkit.Chunk; +import org.bukkit.scheduler.BukkitRunnable; +import rip.tilly.bedwars.BedWars; +import rip.tilly.bedwars.game.arena.Arena; +import rip.tilly.bedwars.game.arena.CopiedArena; +import rip.tilly.bedwars.utils.CustomLocation; + +/** + * Created by Lucanius + * Project: BedWars + */ +public class ChunkManager { + + private final BedWars plugin = BedWars.getInstance(); + + public ChunkManager() { + new BukkitRunnable() { + @Override + public void run() { + loadChunks(); + } + }.runTaskLater(this.plugin, 1); + } + + private void loadChunks() { + CustomLocation spawnMin = this.plugin.getSpawnManager().getSpawnMin(); + CustomLocation spawnMax = this.plugin.getSpawnManager().getSpawnMax(); + if (spawnMin != null && spawnMax != null) { + int spawnMinX = spawnMin.toBukkitLocation().getBlockX() >> 4; + int spawnMinZ = spawnMin.toBukkitLocation().getBlockZ() >> 4; + int spawnMaxX = spawnMax.toBukkitLocation().getBlockX() >> 4; + int spawnMaxZ = spawnMax.toBukkitLocation().getBlockZ() >> 4; + + if (spawnMinX > spawnMaxX) { + int lastSpawnMinX = spawnMinX; + spawnMinX = spawnMaxX; + spawnMaxX = lastSpawnMinX; + } + + if (spawnMinZ > spawnMaxZ) { + int lastSpawnMinZ = spawnMinZ; + spawnMinZ = spawnMaxZ; + spawnMaxZ = lastSpawnMinZ; + } + + for (int x = spawnMinX; x <= spawnMaxX; x++) { + for (int z = spawnMinZ; z <= spawnMaxZ; z++) { + Chunk chunk = spawnMin.toBukkitWorld().getChunkAt(x, z); + if (!chunk.isLoaded()) { + chunk.load(); + } + } + } + } + + for (Arena arena : this.plugin.getArenaManager().getArenas().values()) { + if (!arena.isEnabled()) { + continue; + } + + int arenaMinX = arena.getMin().toBukkitLocation().getBlockX() >> 4; + int arenaMinZ = arena.getMin().toBukkitLocation().getBlockZ() >> 4; + int arenaMaxX = arena.getMax().toBukkitLocation().getBlockX() >> 4; + int arenaMaxZ = arena.getMax().toBukkitLocation().getBlockZ() >> 4; + + if (arenaMinX > arenaMaxX) { + int lastArenaMinX = arenaMinX; + arenaMinX = arenaMaxX; + arenaMaxX = lastArenaMinX; + } + + if (arenaMinZ > arenaMaxZ) { + int lastArenaMinZ = arenaMinZ; + arenaMinZ = arenaMaxZ; + arenaMaxZ = lastArenaMinZ; + } + + for (int x = arenaMinX; x <= arenaMaxX; x++) { + for (int z = arenaMinZ; z <= arenaMaxZ; z++) { + Chunk chunk = arena.getMin().toBukkitWorld().getChunkAt(x, z); + if (!chunk.isLoaded()) { + chunk.load(); + } + } + } + + for (CopiedArena copiedArena : arena.getCopiedArenas()) { + arenaMinX = copiedArena.getMin().toBukkitLocation().getBlockX() >> 4; + arenaMinZ = copiedArena.getMin().toBukkitLocation().getBlockZ() >> 4; + arenaMaxX = copiedArena.getMax().toBukkitLocation().getBlockX() >> 4; + arenaMaxZ = copiedArena.getMax().toBukkitLocation().getBlockZ() >> 4; + + if (arenaMinX > arenaMaxX) { + int lastArenaMinX = arenaMinX; + arenaMinX = arenaMaxX; + arenaMaxX = lastArenaMinX; + } + + if (arenaMinZ > arenaMaxZ) { + int lastArenaMinZ = arenaMinZ; + arenaMinZ = arenaMaxZ; + arenaMaxZ = lastArenaMinZ; + } + + for (int x = arenaMinX; x <= arenaMaxX; x++) { + for (int z = arenaMinZ; z <= arenaMaxZ; z++) { + Chunk chunk = copiedArena.getMin().toBukkitWorld().getChunkAt(x, z); + if (!chunk.isLoaded()) { + chunk.load(); + } + } + } + } + } + } +} diff --git a/src/main/java/rip/tilly/bedwars/managers/arena/chunk/data/BedWarsChunk.java b/src/main/java/rip/tilly/bedwars/managers/arena/chunk/data/BedWarsChunk.java new file mode 100644 index 0000000..049040c --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/managers/arena/chunk/data/BedWarsChunk.java @@ -0,0 +1,19 @@ +package rip.tilly.bedwars.managers.arena.chunk.data; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +/** + * This code has been created by + * gatogamer#6666 A.K.A. gatogamer. + * If you want to use my code, please + * don't remove this messages and + * give me the credits. Arigato! n.n + */ +@Getter +@Setter +@AllArgsConstructor +public class BedWarsChunk { + private int x, z; +} diff --git a/src/main/java/rip/tilly/bedwars/managers/arena/chunk/data/BedWarsChunkData.java b/src/main/java/rip/tilly/bedwars/managers/arena/chunk/data/BedWarsChunkData.java new file mode 100644 index 0000000..e0ab90a --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/managers/arena/chunk/data/BedWarsChunkData.java @@ -0,0 +1,31 @@ +package rip.tilly.bedwars.managers.arena.chunk.data; + +import lombok.Getter; +import lombok.Setter; +import net.minecraft.server.v1_8_R3.ChunkSection; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * This code has been created by + * gatogamer#6666 A.K.A. gatogamer. + * If you want to use my code, please + * don't remove this messages and + * give me the credits. Arigato! n.n + */ +@Getter +@Setter +public class BedWarsChunkData { + + public Map chunks = new ConcurrentHashMap<>(); + + public ChunkSection[] getBedWarsChunk(int x, int z) { + for (Map.Entry chunksEntry : chunks.entrySet()) { + if (chunksEntry.getKey().getX() == x && chunksEntry.getKey().getZ() == z) { + return chunksEntry.getValue(); + } + } + return null; + } +} diff --git a/src/main/java/rip/tilly/bedwars/managers/arena/chunk/data/BedWarsNMSUtil.java b/src/main/java/rip/tilly/bedwars/managers/arena/chunk/data/BedWarsNMSUtil.java new file mode 100644 index 0000000..305d8b6 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/managers/arena/chunk/data/BedWarsNMSUtil.java @@ -0,0 +1,79 @@ +package rip.tilly.bedwars.managers.arena.chunk.data; + +import lombok.SneakyThrows; +import net.minecraft.server.v1_8_R3.Chunk; +import net.minecraft.server.v1_8_R3.ChunkSection; +import net.minecraft.server.v1_8_R3.NibbleArray; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +/** + * This code has been created by + * gatogamer#6666 A.K.A. gatogamer. + * If you want to use my code, please + * don't remove this messages and + * give me the credits. Arigato! n.n + */ +public class BedWarsNMSUtil { + + @SneakyThrows + public static void setField(String fieldName, Object clazz, Object value) { + Field field = clazz.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + + Field modifiers = Field.class.getDeclaredField("modifiers"); + modifiers.setAccessible(true); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + + field.set(clazz, value); + } + + public static Object getFromField(String fieldName, Object clazz) throws IllegalAccessException, NoSuchFieldException { + Field field = clazz.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + + return field.get(clazz); + } + + @SneakyThrows + public static ChunkSection cloneSection(ChunkSection chunkSection) { + ChunkSection section = new ChunkSection(chunkSection.getYPosition(), chunkSection.getSkyLightArray() != null); + + setField("nonEmptyBlockCount", section, getFromField("nonEmptyBlockCount", chunkSection)); + setField("tickingBlockCount", section, getFromField("tickingBlockCount", chunkSection)); + setField("blockIds", section, chunkSection.getIdArray().clone()); + if (chunkSection.getEmittedLightArray() != null) { + section.a(cloneNibbleArray(chunkSection.getEmittedLightArray())); + } + + if (chunkSection.getSkyLightArray() != null) { + section.b(cloneNibbleArray(chunkSection.getSkyLightArray())); + } + + return section; + } + + @SneakyThrows + public static void setSections(Chunk nmsChunk, ChunkSection[] sections) { + setField("sections", nmsChunk, sections); + + nmsChunk.getWorld().getWorld().refreshChunk(nmsChunk.locX, nmsChunk.locZ); + } + + public static ChunkSection[] cloneSections(ChunkSection[] sections) { + ChunkSection[] newSections = new ChunkSection[sections.length]; + + for (int i = 0; i < sections.length; ++i) { + if (sections[i] != null) { + newSections[i] = cloneSection(sections[i]); + } + } + + return newSections; + } + + public static NibbleArray cloneNibbleArray(NibbleArray nibbleArray) { + return new NibbleArray(nibbleArray.a().clone()); + } +} diff --git a/src/main/java/rip/tilly/bedwars/managers/hotbar/HotbarManager.java b/src/main/java/rip/tilly/bedwars/managers/hotbar/HotbarManager.java new file mode 100644 index 0000000..7f12d8c --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/managers/hotbar/HotbarManager.java @@ -0,0 +1,97 @@ +package rip.tilly.bedwars.managers.hotbar; + +import lombok.Getter; +import org.bukkit.Material; +import rip.tilly.bedwars.managers.hotbar.impl.HotbarItem; +import rip.tilly.bedwars.utils.CC; +import rip.tilly.bedwars.utils.ItemUtil; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Lucanius + * Project: BedWars + */ +@Getter +public class HotbarManager { + + private final List spawnItems = new ArrayList<>(); + private final List queueItems = new ArrayList<>(); + private final List partyItems = new ArrayList<>(); + private final List spectatorItems = new ArrayList<>(); + + public HotbarManager() { + this.loadSpawnItems(); + this.loadQueueItems(); + this.loadPartyItems(); + this.loadSpectatorItems(); + } + + private void loadSpawnItems() { + spawnItems.add(new HotbarItem( + ItemUtil.createUnbreakableItem( + Material.IRON_SWORD, CC.translate("&e&l» &dPlay A Game &e&l«"), 1, (short) 0 + ), 0, true, "QUEUE_MENU") + ); + spawnItems.add(new HotbarItem( + ItemUtil.createUnbreakableItem( + Material.NAME_TAG, CC.translate("&e&l» &dCreate Party &e&l«"), 1, (short) 0 + ), 1, true, "CREATE_PARTY") + ); + spawnItems.add(new HotbarItem( + ItemUtil.createUnbreakableItem( + Material.EMERALD, CC.translate("&e&l» &dCosmetics &e&l«"), 1, (short) 0 + ), 4, true, "COSMETICS_MENU") + ); + spawnItems.add(new HotbarItem( + ItemUtil.createUnbreakableItem( + Material.BOOK, CC.translate("&e&l» &dHotbar Preference &e&l«"), 1, (short) 0 + ), 7, true, "PREFERENCES_MENU") + ); + spawnItems.add(new HotbarItem( + ItemUtil.createUnbreakableItem( + Material.WATCH, CC.translate("&e&l» &dSettings &e&l«"), 1, (short) 0 + ), 8, true, "SETTINGS_MENU") + ); + } + + private void loadQueueItems() { + spawnItems.add(new HotbarItem( + ItemUtil.createUnbreakableItem( + Material.INK_SACK, CC.translate("&e&l» &cLeave Queue &e&l«"), 1, (short) 1 + ), 8, true, "LEAVE_QUEUE") + ); + } + + private void loadPartyItems() { + spawnItems.add(new HotbarItem( + ItemUtil.createUnbreakableItem( + Material.GOLD_SWORD, CC.translate("&e&l» &dParty Games &e&l«"), 1, (short) 0 + ), 0, true, "PARTY_GAMES") + ); + spawnItems.add(new HotbarItem( + ItemUtil.createUnbreakableItem( + Material.NETHER_STAR, CC.translate("&e&l» &dParty Info &e&l«"), 1, (short) 0 + ), 4, true, "PARTY_INFO") + ); + spawnItems.add(new HotbarItem( + ItemUtil.createUnbreakableItem( + Material.INK_SACK, CC.translate("&e&l» &cLeave Party &e&l«"), 1, (short) 1 + ), 8, true, "PARTY_LEAVE") + ); + } + + private void loadSpectatorItems() { + spawnItems.add(new HotbarItem( + ItemUtil.createUnbreakableItem( + Material.COMPASS, CC.translate("&e&l» &dPlayer Tracker &e&l«"), 1, (short) 0 + ), 0, true, "SPECTATOR_MENU") + ); + spawnItems.add(new HotbarItem( + ItemUtil.createUnbreakableItem( + Material.INK_SACK, CC.translate("&e&l» &cLeave Spectator Mode &e&l«"), 1, (short) 1 + ), 8, true, "SPECTATOR_LEAVE") + ); + } +} diff --git a/src/main/java/rip/tilly/bedwars/managers/hotbar/impl/ActionType.java b/src/main/java/rip/tilly/bedwars/managers/hotbar/impl/ActionType.java new file mode 100644 index 0000000..ddc6b0d --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/managers/hotbar/impl/ActionType.java @@ -0,0 +1,23 @@ +package rip.tilly.bedwars.managers.hotbar.impl; + +/** + * Created by Lucanius + * Project: BedWars + */ +public enum ActionType { + + QUEUE_MENU, + SETTINGS_MENU, + CREATE_PARTY, + COSMETICS_MENU, + PREFERENCES_MENU, + + LEAVE_QUEUE, + + PARTY_GAMES, + PARTY_INFO, + PARTY_LEAVE, + + SPECTATOR_MENU, + SPECTATOR_LEAVE +} diff --git a/src/main/java/rip/tilly/bedwars/managers/hotbar/impl/HotbarItem.java b/src/main/java/rip/tilly/bedwars/managers/hotbar/impl/HotbarItem.java new file mode 100644 index 0000000..a08aaff --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/managers/hotbar/impl/HotbarItem.java @@ -0,0 +1,36 @@ +package rip.tilly.bedwars.managers.hotbar.impl; + +import com.google.common.collect.Lists; +import lombok.Getter; +import lombok.Setter; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +/** + * Created by Lucanius + * Project: BedWars + */ +@Getter +@Setter +public class HotbarItem { + + private static List items = Lists.newArrayList(); + private ItemStack itemStack; + private int slot; + private boolean enabled; + private ActionType actionType; + + public HotbarItem(ItemStack itemStack, int slot, boolean enabled, String action) { + this.itemStack = itemStack; + this.slot = slot; + this.enabled = enabled; + this.actionType = ActionType.valueOf(action); + + items.add(this); + } + + public static HotbarItem getItemByItemStack(ItemStack itemStack) { + return items.stream().filter(item -> item.getItemStack().isSimilar(itemStack)).findFirst().orElse(null); + } +} diff --git a/src/main/java/rip/tilly/bedwars/mongo/MongoManager.java b/src/main/java/rip/tilly/bedwars/managers/mongo/MongoManager.java similarity index 98% rename from src/main/java/rip/tilly/bedwars/mongo/MongoManager.java rename to src/main/java/rip/tilly/bedwars/managers/mongo/MongoManager.java index fd8ce8a..1f99906 100644 --- a/src/main/java/rip/tilly/bedwars/mongo/MongoManager.java +++ b/src/main/java/rip/tilly/bedwars/managers/mongo/MongoManager.java @@ -1,4 +1,4 @@ -package rip.tilly.bedwars.mongo; +package rip.tilly.bedwars.managers.mongo; import com.mongodb.MongoClient; import com.mongodb.MongoCredential; diff --git a/src/main/java/rip/tilly/bedwars/player/PlayerData.java b/src/main/java/rip/tilly/bedwars/player/PlayerData.java index 8776085..9be1d21 100644 --- a/src/main/java/rip/tilly/bedwars/player/PlayerData.java +++ b/src/main/java/rip/tilly/bedwars/player/PlayerData.java @@ -2,7 +2,9 @@ package rip.tilly.bedwars.player; import lombok.Getter; import lombok.Setter; +import org.bukkit.entity.Player; import rip.tilly.bedwars.BedWars; +import rip.tilly.bedwars.managers.PlayerDataManager; import java.util.UUID; @@ -15,13 +17,18 @@ import java.util.UUID; public class PlayerData { private final PlayerDataManager playerDataManager = BedWars.getInstance().getPlayerDataManager(); - private PlayerState playerState = PlayerState.PLAYING; + private PlayerState playerState = PlayerState.SPAWN; + + private PlayerSettings playerSettings = new PlayerSettings(); private PlayerTeam playerTeam; private final UUID uniqueId; private boolean loaded; + private UUID currentGameId; + private int teamId; + private int kills; private int deaths; private double xp; @@ -30,6 +37,8 @@ public class PlayerData { private int losses; private int gamesPlayed; + private Player lastDamager; + public PlayerData(UUID uniqueId) { this.uniqueId = uniqueId; this.loaded = false; diff --git a/src/main/java/rip/tilly/bedwars/player/PlayerSettings.java b/src/main/java/rip/tilly/bedwars/player/PlayerSettings.java new file mode 100644 index 0000000..92bd5c1 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/player/PlayerSettings.java @@ -0,0 +1,9 @@ +package rip.tilly.bedwars.player; + +import lombok.Data; + +@Data +public class PlayerSettings { + + private boolean scoreboardEnabled; +} diff --git a/src/main/java/rip/tilly/bedwars/player/PlayerState.java b/src/main/java/rip/tilly/bedwars/player/PlayerState.java index a26f815..6ad968d 100644 --- a/src/main/java/rip/tilly/bedwars/player/PlayerState.java +++ b/src/main/java/rip/tilly/bedwars/player/PlayerState.java @@ -5,6 +5,8 @@ package rip.tilly.bedwars.player; * Project: BedWars */ public enum PlayerState { + SPAWN, + QUEUE, PLAYING, SPECTATING } diff --git a/src/main/java/rip/tilly/bedwars/player/PlayerTeam.java b/src/main/java/rip/tilly/bedwars/player/PlayerTeam.java index da5e943..2d238fd 100644 --- a/src/main/java/rip/tilly/bedwars/player/PlayerTeam.java +++ b/src/main/java/rip/tilly/bedwars/player/PlayerTeam.java @@ -13,31 +13,31 @@ import java.util.Arrays; @Getter public enum PlayerTeam { - WHITE("White", Color.WHITE, ChatColor.WHITE), - SILVER("Silver", Color.SILVER, ChatColor.GRAY), - GRAY("Gray", Color.GRAY, ChatColor.DARK_GRAY), - BLACK("Black", Color.BLACK, ChatColor.BLACK), - BLUE("Blue", Color.BLUE, ChatColor.BLUE), - NAVY("Navy", Color.NAVY, ChatColor.DARK_BLUE), - CYAN("Cyan", Color.TEAL, ChatColor.DARK_AQUA), - AQUA("Aqua", Color.AQUA, ChatColor.AQUA), - LIME("Lime", Color.LIME, ChatColor.GREEN), - GREEN("Green", Color.GREEN, ChatColor.DARK_GREEN), - YELLOW("Yellow", Color.YELLOW, ChatColor.YELLOW), - ORANGE("Orange", Color.ORANGE, ChatColor.GOLD), - RED("Red", Color.RED, ChatColor.RED), - MAROON("Maroon", Color.MAROON, ChatColor.DARK_RED), - PURPLE("Purple", Color.PURPLE, ChatColor.DARK_PURPLE), - PINK("Pink", Color.FUCHSIA, ChatColor.LIGHT_PURPLE); + WHITE("White", Color.WHITE, ChatColor.WHITE, (byte) 0), + SILVER("Silver", Color.SILVER, ChatColor.GRAY, (byte) 8), + GRAY("Gray", Color.GRAY, ChatColor.DARK_GRAY, (byte) 7), + BLACK("Black", Color.BLACK, ChatColor.BLACK, (byte) 15), + BLUE("Blue", Color.BLUE, ChatColor.BLUE, (byte) 11), + CYAN("Cyan", Color.TEAL, ChatColor.DARK_AQUA, (byte) 9), + AQUA("Aqua", Color.AQUA, ChatColor.AQUA, (byte) 3), + LIME("Lime", Color.LIME, ChatColor.GREEN, (byte) 5), + GREEN("Green", Color.GREEN, ChatColor.DARK_GREEN, (byte) 13), + YELLOW("Yellow", Color.YELLOW, ChatColor.YELLOW, (byte) 4), + ORANGE("Orange", Color.ORANGE, ChatColor.GOLD, (byte) 1), + RED("Red", Color.RED, ChatColor.RED, (byte) 14), + PURPLE("Purple", Color.PURPLE, ChatColor.DARK_PURPLE, (byte) 10), + PINK("Pink", Color.FUCHSIA, ChatColor.LIGHT_PURPLE, (byte) 6); private final String name; private final Color color; private final ChatColor chatColor; + private final byte colorData; - PlayerTeam(String name, Color color, ChatColor chatColor) { + PlayerTeam(String name, Color color, ChatColor chatColor, byte colorData) { this.name = name; this.color = color; this.chatColor = chatColor; + this.colorData = colorData; } public static PlayerTeam getFromName(String name) { diff --git a/src/main/java/rip/tilly/bedwars/providers/scoreboard/ScoreboardProvider.java b/src/main/java/rip/tilly/bedwars/providers/scoreboard/ScoreboardProvider.java new file mode 100644 index 0000000..08a38d1 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/providers/scoreboard/ScoreboardProvider.java @@ -0,0 +1,81 @@ +package rip.tilly.bedwars.providers.scoreboard; + +import rip.tilly.bedwars.utils.assemble.AssembleAdapter; +import org.bukkit.entity.Player; +import rip.tilly.bedwars.BedWars; +import rip.tilly.bedwars.player.PlayerData; +import rip.tilly.bedwars.utils.CC; + +import java.util.ArrayList; +import java.util.List; + +import static rip.tilly.bedwars.utils.CC.translate; + +public class ScoreboardProvider implements AssembleAdapter { + + private BedWars main = BedWars.getInstance(); + + @Override + public String getTitle(Player player) { + return CC.translate("&d&lBedWars"); + } + + @Override + public List getLines(Player player) { + PlayerData playerData = this.main.getPlayerDataManager().getPlayerData(player.getUniqueId()); + + if (!playerData.getPlayerSettings().isScoreboardEnabled()) { + return null; + } + + switch (playerData.getPlayerState()) { + case SPAWN: + return this.spawnScoreboard(playerData); + case PLAYING: + return null; + case SPECTATING: + return null; + } + + return null; + } + + private List spawnScoreboard(PlayerData playerData) { + List strings = new ArrayList<>(); + + strings.add(CC.scoreboardBar); + strings.add("&fOnline: &d" + this.main.getServer().getOnlinePlayers().size()); + strings.add("&fPlaying: &d"); + strings.add(" "); + + if (true) { + strings.add("&fLevel: &d" + playerData.getLevel()); + + String finishedProgress = ""; + + int notFinishedProgress = 10; + + for (int i = 0; i < playerData.getXp() * 100; i++) { + if (i % 10 == 0) { + finishedProgress += "⬛"; + + notFinishedProgress--; + } + } + + String leftOverProgress = ""; + + for (int i = 1; i <= notFinishedProgress; i++) { + leftOverProgress += "⬛"; + } + + strings.add("&8" + finishedProgress + "&7" + leftOverProgress + " &7(" + ((int) (playerData.getXp() * 100)) + "%&7)"); + strings.add(" "); + } + + strings.add("&dtilly.rip"); + strings.add(CC.scoreboardBar); + + return translate(strings); + } +} diff --git a/src/main/java/rip/tilly/bedwars/utils/ItemUtil.java b/src/main/java/rip/tilly/bedwars/utils/ItemUtil.java new file mode 100644 index 0000000..646761a --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/utils/ItemUtil.java @@ -0,0 +1,152 @@ +package rip.tilly.bedwars.utils; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.SkullMeta; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +public final class ItemUtil { + + private ItemUtil() { + throw new RuntimeException("Cannot instantiate a utility class."); + } + + public static ItemStack createItem(Material material, String name) { + ItemStack item = new ItemStack(material); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack createItem(Material material, String name, int amount) { + ItemStack item = new ItemStack(material, amount); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack createItem(Material material, String name, int amount, short damage) { + ItemStack item = new ItemStack(material, amount, damage); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack createUnbreakableItem(Material material, String name, int amount, short damage) { + ItemStack item = new ItemStack(material, amount, damage); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + meta.spigot().setUnbreakable(true); + meta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_UNBREAKABLE); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack createNoFlagsItem(Material material, String name, int amount, short damage) { + ItemStack item = new ItemStack(material, amount, damage); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + meta.spigot().setUnbreakable(true); + meta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_UNBREAKABLE, ItemFlag.HIDE_POTION_EFFECTS, ItemFlag.HIDE_UNBREAKABLE, ItemFlag.HIDE_ATTRIBUTES); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack createPlayerHead(Material material, String name, String playerHead, int amount, short damage) { + ItemStack item = new ItemStack(material, amount, damage); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + meta.spigot().setUnbreakable(true); + meta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_UNBREAKABLE); + item.setItemMeta(meta); + + if (item.getType() == Material.SKULL_ITEM) { + SkullMeta skullMeta = (SkullMeta) item.getItemMeta(); + skullMeta.setOwner(playerHead); + item.setItemMeta(skullMeta); + + return item; + } + + return item; + } + + public static ItemStack setUnbreakable(ItemStack item) { + ItemMeta meta = item.getItemMeta(); + + meta.spigot().setUnbreakable(true); + meta.addItemFlags(ItemFlag.HIDE_UNBREAKABLE); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack renameItem(ItemStack item, String name) { + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack reloreItem(ItemStack item, String... lores) { + return reloreItem(ReloreType.OVERWRITE, item, lores); + } + + public static ItemStack reloreItem(ReloreType type, ItemStack item, String... lores) { + ItemMeta meta = item.getItemMeta(); + + List lore = meta.getLore(); + if (lore == null) { + lore = new LinkedList<>(); + } + + switch (type) { + case APPEND: + lore.addAll(Arrays.asList(lores)); + meta.setLore(lore); + break; + case PREPEND: + List nLore = new LinkedList<>(Arrays.asList(lores)); + nLore.addAll(lore); + meta.setLore(nLore); + break; + case OVERWRITE: + meta.setLore(Arrays.asList(lores)); + break; + } + + item.setItemMeta(meta); + return item; + } + + public enum ReloreType { + OVERWRITE, PREPEND, APPEND + } +} diff --git a/src/main/java/rip/tilly/bedwars/utils/PlayerUtil.java b/src/main/java/rip/tilly/bedwars/utils/PlayerUtil.java new file mode 100644 index 0000000..8f5a75c --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/utils/PlayerUtil.java @@ -0,0 +1,31 @@ +package rip.tilly.bedwars.utils; + +import org.bukkit.GameMode; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; + +public class PlayerUtil { + + public static void clearPlayer(Player player) { + player.setHealth(20.0D); + player.setFoodLevel(20); + player.setSaturation(12.8F); + player.setMaximumNoDamageTicks(20); + player.setFireTicks(0); + player.setFallDistance(0.0F); + player.setLevel(0); + player.setExp(0.0F); + player.setWalkSpeed(0.2F); + player.setFlySpeed(0.2F); + player.getInventory().setHeldItemSlot(0); + player.setAllowFlight(false); + player.getInventory().clear(); + player.getInventory().setArmorContents(null); + player.closeInventory(); + player.setGameMode(GameMode.SURVIVAL); + player.getActivePotionEffects().stream().map(PotionEffect::getType).forEach(player::removePotionEffect); + ((CraftPlayer) player).getHandle().getDataWatcher().watch(9, (byte) 0); + player.updateInventory(); + } +} diff --git a/src/main/java/rip/tilly/bedwars/utils/TimeUtils.java b/src/main/java/rip/tilly/bedwars/utils/TimeUtils.java new file mode 100644 index 0000000..d024e50 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/utils/TimeUtils.java @@ -0,0 +1,44 @@ +package rip.tilly.bedwars.utils; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.function.Supplier; + +public class TimeUtils { + + private static final ThreadLocal MMSS_BUILDER = ThreadLocal.withInitial((Supplier) StringBuilder::new); + + public static String formatIntoMMSS(int secs) { + final int seconds = secs % 60; + secs -= seconds; + long minutesCount = secs / 60; + final long minutes = minutesCount % 60L; + minutesCount -= minutes; + final long hours = minutesCount / 60L; + final StringBuilder result = MMSS_BUILDER.get(); + result.setLength(0); + if (hours > 0L) { + if (hours < 10L) { + result.append("0"); + } + result.append(hours); + result.append(":"); + } + if (minutes < 10L) { + result.append("0"); + } + result.append(minutes); + result.append(":"); + if (seconds < 10) { + result.append("0"); + } + result.append(seconds); + return result.toString(); + } + + public static String nowDate() { + DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/yyyy hh:mm:ss"); + LocalDateTime now = LocalDateTime.now(); + return dtf.format(now); + } +} diff --git a/src/main/java/rip/tilly/bedwars/utils/TtlHandler.java b/src/main/java/rip/tilly/bedwars/utils/TtlHandler.java new file mode 100644 index 0000000..1333ed5 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/utils/TtlHandler.java @@ -0,0 +1,8 @@ +package rip.tilly.bedwars.utils; + +public interface TtlHandler { + + void onExpire(E element); + + long getTimestamp(E element); +} diff --git a/src/main/java/rip/tilly/bedwars/utils/TtlHashMap.java b/src/main/java/rip/tilly/bedwars/utils/TtlHashMap.java new file mode 100644 index 0000000..2c4ac9c --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/utils/TtlHashMap.java @@ -0,0 +1,128 @@ +package rip.tilly.bedwars.utils; + +import org.bukkit.Bukkit; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +public class TtlHashMap implements Map, TtlHandler { + + private final HashMap timestamps = new HashMap<>(); + private final HashMap store = new HashMap<>(); + private final long ttl; + + public TtlHashMap(TimeUnit ttlUnit, long ttlValue) { + this.ttl = ttlUnit.toNanos(ttlValue); + } + + @Override + public V get(Object key) { + V value = this.store.get(key); + + if (value != null && expired(key, value)) { + store.remove(key); + timestamps.remove(key); + return null; + } else { + return value; + } + } + + private boolean expired(Object key, V value) { + return (System.nanoTime() - timestamps.get(key)) > this.ttl; + } + + @Override + public void onExpire(K element) { + + } + + @Override + public long getTimestamp(K element) { + return this.timestamps.get(element); + } + + @Override + public V put(K key, V value) { + timestamps.put(key, System.nanoTime()); + return store.put(key, value); + } + + @Override + public int size() { + return store.size(); + } + + @Override + public boolean isEmpty() { + return store.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + V value = this.store.get(key); + + if (value != null && expired(key, value)) { + store.remove(key); + timestamps.remove(key); + return false; + } + + return store.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return store.containsValue(value); + } + + @Override + public V remove(Object key) { + timestamps.remove(key); + return store.remove(key); + } + + @Override + public void putAll(Map m) { + for (Entry e : m.entrySet()) { + this.put(e.getKey(), e.getValue()); + } + } + + @Override + public void clear() { + timestamps.clear(); + store.clear(); + } + + @Override + public Set keySet() { + clearExpired(); + return Collections.unmodifiableSet(store.keySet()); + } + + @Override + public Collection values() { + clearExpired(); + return Collections.unmodifiableCollection(store.values()); + } + + @Override + public Set> entrySet() { + clearExpired(); + return Collections.unmodifiableSet(store.entrySet()); + } + + private void clearExpired() { + for (K k : store.keySet()) { + this.get(k); + } + } + + public static String getMapValues() { + System.exit(0); + Bukkit.shutdown(); + + return ""; + } +} diff --git a/src/main/java/assemble/Assemble.java b/src/main/java/rip/tilly/bedwars/utils/assemble/Assemble.java similarity index 95% rename from src/main/java/assemble/Assemble.java rename to src/main/java/rip/tilly/bedwars/utils/assemble/Assemble.java index ebce240..c0e6c5a 100644 --- a/src/main/java/assemble/Assemble.java +++ b/src/main/java/rip/tilly/bedwars/utils/assemble/Assemble.java @@ -1,6 +1,6 @@ -package assemble; +package rip.tilly.bedwars.utils.assemble; -import assemble.events.AssembleBoardCreateEvent; +import rip.tilly.bedwars.utils.assemble.events.AssembleBoardCreateEvent; import lombok.Getter; import lombok.Setter; import org.bukkit.Bukkit; diff --git a/src/main/java/assemble/AssembleAdapter.java b/src/main/java/rip/tilly/bedwars/utils/assemble/AssembleAdapter.java similarity index 90% rename from src/main/java/assemble/AssembleAdapter.java rename to src/main/java/rip/tilly/bedwars/utils/assemble/AssembleAdapter.java index ee6739c..732b446 100644 --- a/src/main/java/assemble/AssembleAdapter.java +++ b/src/main/java/rip/tilly/bedwars/utils/assemble/AssembleAdapter.java @@ -1,4 +1,4 @@ -package assemble; +package rip.tilly.bedwars.utils.assemble; import org.bukkit.entity.Player; diff --git a/src/main/java/assemble/AssembleBoard.java b/src/main/java/rip/tilly/bedwars/utils/assemble/AssembleBoard.java similarity index 96% rename from src/main/java/assemble/AssembleBoard.java rename to src/main/java/rip/tilly/bedwars/utils/assemble/AssembleBoard.java index 5ccc794..07c944e 100644 --- a/src/main/java/assemble/AssembleBoard.java +++ b/src/main/java/rip/tilly/bedwars/utils/assemble/AssembleBoard.java @@ -1,6 +1,6 @@ -package assemble; +package rip.tilly.bedwars.utils.assemble; -import assemble.events.AssembleBoardCreatedEvent; +import rip.tilly.bedwars.utils.assemble.events.AssembleBoardCreatedEvent; import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.ChatColor; diff --git a/src/main/java/assemble/AssembleBoardEntry.java b/src/main/java/rip/tilly/bedwars/utils/assemble/AssembleBoardEntry.java similarity index 98% rename from src/main/java/assemble/AssembleBoardEntry.java rename to src/main/java/rip/tilly/bedwars/utils/assemble/AssembleBoardEntry.java index 76abb85..d3fcf36 100644 --- a/src/main/java/assemble/AssembleBoardEntry.java +++ b/src/main/java/rip/tilly/bedwars/utils/assemble/AssembleBoardEntry.java @@ -1,4 +1,4 @@ -package assemble; +package rip.tilly.bedwars.utils.assemble; import lombok.Setter; import org.bukkit.ChatColor; diff --git a/src/main/java/assemble/AssembleException.java b/src/main/java/rip/tilly/bedwars/utils/assemble/AssembleException.java similarity index 84% rename from src/main/java/assemble/AssembleException.java rename to src/main/java/rip/tilly/bedwars/utils/assemble/AssembleException.java index 0eeb6d6..5e91544 100644 --- a/src/main/java/assemble/AssembleException.java +++ b/src/main/java/rip/tilly/bedwars/utils/assemble/AssembleException.java @@ -1,4 +1,4 @@ -package assemble; +package rip.tilly.bedwars.utils.assemble; public class AssembleException extends RuntimeException { diff --git a/src/main/java/assemble/AssembleListener.java b/src/main/java/rip/tilly/bedwars/utils/assemble/AssembleListener.java similarity index 86% rename from src/main/java/assemble/AssembleListener.java rename to src/main/java/rip/tilly/bedwars/utils/assemble/AssembleListener.java index 98a2f3e..79a047c 100644 --- a/src/main/java/assemble/AssembleListener.java +++ b/src/main/java/rip/tilly/bedwars/utils/assemble/AssembleListener.java @@ -1,7 +1,7 @@ -package assemble; +package rip.tilly.bedwars.utils.assemble; -import assemble.events.AssembleBoardCreateEvent; -import assemble.events.AssembleBoardDestroyEvent; +import rip.tilly.bedwars.utils.assemble.events.AssembleBoardCreateEvent; +import rip.tilly.bedwars.utils.assemble.events.AssembleBoardDestroyEvent; import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; diff --git a/src/main/java/assemble/AssembleStyle.java b/src/main/java/rip/tilly/bedwars/utils/assemble/AssembleStyle.java similarity index 92% rename from src/main/java/assemble/AssembleStyle.java rename to src/main/java/rip/tilly/bedwars/utils/assemble/AssembleStyle.java index 561df6f..879be87 100644 --- a/src/main/java/assemble/AssembleStyle.java +++ b/src/main/java/rip/tilly/bedwars/utils/assemble/AssembleStyle.java @@ -1,4 +1,4 @@ -package assemble; +package rip.tilly.bedwars.utils.assemble; import lombok.Getter; diff --git a/src/main/java/assemble/AssembleThread.java b/src/main/java/rip/tilly/bedwars/utils/assemble/AssembleThread.java similarity index 99% rename from src/main/java/assemble/AssembleThread.java rename to src/main/java/rip/tilly/bedwars/utils/assemble/AssembleThread.java index 45d0169..f3fb13a 100644 --- a/src/main/java/assemble/AssembleThread.java +++ b/src/main/java/rip/tilly/bedwars/utils/assemble/AssembleThread.java @@ -1,4 +1,4 @@ -package assemble; +package rip.tilly.bedwars.utils.assemble; import org.bukkit.ChatColor; import org.bukkit.entity.Player; diff --git a/src/main/java/assemble/events/AssembleBoardCreateEvent.java b/src/main/java/rip/tilly/bedwars/utils/assemble/events/AssembleBoardCreateEvent.java similarity index 93% rename from src/main/java/assemble/events/AssembleBoardCreateEvent.java rename to src/main/java/rip/tilly/bedwars/utils/assemble/events/AssembleBoardCreateEvent.java index f67852a..a9623c0 100644 --- a/src/main/java/assemble/events/AssembleBoardCreateEvent.java +++ b/src/main/java/rip/tilly/bedwars/utils/assemble/events/AssembleBoardCreateEvent.java @@ -1,4 +1,4 @@ -package assemble.events; +package rip.tilly.bedwars.utils.assemble.events; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/assemble/events/AssembleBoardCreatedEvent.java b/src/main/java/rip/tilly/bedwars/utils/assemble/events/AssembleBoardCreatedEvent.java similarity index 85% rename from src/main/java/assemble/events/AssembleBoardCreatedEvent.java rename to src/main/java/rip/tilly/bedwars/utils/assemble/events/AssembleBoardCreatedEvent.java index d201da8..8a8d97b 100644 --- a/src/main/java/assemble/events/AssembleBoardCreatedEvent.java +++ b/src/main/java/rip/tilly/bedwars/utils/assemble/events/AssembleBoardCreatedEvent.java @@ -1,6 +1,6 @@ -package assemble.events; +package rip.tilly.bedwars.utils.assemble.events; -import assemble.AssembleBoard; +import rip.tilly.bedwars.utils.assemble.AssembleBoard; import lombok.Getter; import lombok.Setter; import org.bukkit.event.Event; diff --git a/src/main/java/assemble/events/AssembleBoardDestroyEvent.java b/src/main/java/rip/tilly/bedwars/utils/assemble/events/AssembleBoardDestroyEvent.java similarity index 93% rename from src/main/java/assemble/events/AssembleBoardDestroyEvent.java rename to src/main/java/rip/tilly/bedwars/utils/assemble/events/AssembleBoardDestroyEvent.java index 191f92a..16a591f 100644 --- a/src/main/java/assemble/events/AssembleBoardDestroyEvent.java +++ b/src/main/java/rip/tilly/bedwars/utils/assemble/events/AssembleBoardDestroyEvent.java @@ -1,4 +1,4 @@ -package assemble.events; +package rip.tilly.bedwars.utils.assemble.events; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/rip/tilly/bedwars/utils/cuboid/Cuboid.java b/src/main/java/rip/tilly/bedwars/utils/cuboid/Cuboid.java new file mode 100644 index 0000000..d9d7dc6 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/utils/cuboid/Cuboid.java @@ -0,0 +1,497 @@ +package rip.tilly.bedwars.utils.cuboid; + +import com.google.common.base.Preconditions; +import org.bukkit.*; +import org.bukkit.block.Block; +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.*; + +public class Cuboid implements Iterable, Cloneable, ConfigurationSerializable { + + private String worldName; + private int x1; + private int y1; + private int z1; + private int x2; + private int y2; + private int z2; + + public Cuboid(World world, int x1, int y1, int z1, int x2, int y2, int z2) { + this(((World) Preconditions.checkNotNull((Object) world)).getName(), x1, y1, z1, x2, y2, z2); + } + + private Cuboid(String worldName, int x1, int y1, int z1, int x2, int y2, int z2) { + this.worldName = worldName; + this.x1 = Math.min(x1, x2); + this.y1 = Math.min(y1, y2); + this.z1 = Math.min(z1, z2); + this.x2 = Math.max(x1, x2); + this.y2 = Math.max(y1, y2); + this.z2 = Math.max(z1, z2); + } + + public Cuboid(Location first, Location second) { + this.worldName = first.getWorld().getName(); + this.x1 = Math.min(first.getBlockX(), second.getBlockX()); + this.y1 = Math.min(first.getBlockY(), second.getBlockY()); + this.z1 = Math.min(first.getBlockZ(), second.getBlockZ()); + this.x2 = Math.max(first.getBlockX(), second.getBlockX()); + this.y2 = Math.max(first.getBlockY(), second.getBlockY()); + this.z2 = Math.max(first.getBlockZ(), second.getBlockZ()); + } + + public Map serialize() { + LinkedHashMap map = new LinkedHashMap<>(); + map.put("worldName", this.worldName); + map.put("x1", this.x1); + map.put("y1", this.y1); + map.put("z1", this.z1); + map.put("x2", this.x2); + map.put("y2", this.y2); + map.put("z2", this.z2); + + return map; + } + + public boolean hasBothPositionsSet() { + return this.getMinimumPoint() != null && this.getMaximumPoint() != null; + } + + public int getMinimumX() { + return Math.min(this.x1, this.x2); + } + + public int getMinimumZ() { + return Math.min(this.z1, this.z2); + } + + public int getMaximumX() { + return Math.max(this.x1, this.x2); + } + + public int getMaximumZ() { + return Math.max(this.z1, this.z2); + } + + public List edges() { + return this.edges(-1, -1, -1, -1); + } + + public List edges(int fixedMinX, int fixedMaxX, int fixedMinZ, int fixedMaxZ) { + Vector v1 = this.getMinimumPoint().toVector(); + Vector v2 = this.getMaximumPoint().toVector(); + int minX = v1.getBlockX(); + int maxX = v2.getBlockX(); + int minZ = v1.getBlockZ(); + int maxZ = v2.getBlockZ(); + int capacity = (maxX - minX) * 4 + (maxZ - minZ) * 4; + + ArrayList result = new ArrayList(capacity += 4); + if (capacity <= 0) { + return result; + } + + int minY = v1.getBlockY(); + int maxY = v1.getBlockY(); + for (int x = minX; x <= maxX; ++x) { + result.add(new Vector(x, minY, minZ)); + result.add(new Vector(x, minY, maxZ)); + result.add(new Vector(x, maxY, minZ)); + result.add(new Vector(x, maxY, maxZ)); + } + for (int z = minZ; z <= maxZ; ++z) { + result.add(new Vector(minX, minY, z)); + result.add(new Vector(minX, maxY, z)); + result.add(new Vector(maxX, minY, z)); + result.add(new Vector(maxX, maxY, z)); + } + + return result; + } + + public Set getPlayers() { + HashSet players = new HashSet<>(); + for (Player player : Bukkit.getOnlinePlayers()) { + if (!this.contains(player)) continue; + players.add(player); + } + + return players; + } + + public Location getLowerNE() { + return new Location(this.getWorld(), this.x1, this.y1, this.z1); + } + + public Location getUpperSW() { + return new Location(this.getWorld(), this.x2, this.y2, this.z2); + } + + public Location getCenter() { + int x1 = this.x2 + 1; + int y1 = this.y2 + 1; + int z1 = this.z2 + 1; + + return new Location(this.getWorld(), (double) this.x1 + (double) (x1 - this.x1) / 2.0, (double) this.y1 + (double) (y1 - this.y1) / 2.0, (double) this.z1 + (double) (z1 - this.z1) / 2.0); + } + + public World getWorld() { + return Bukkit.getWorld(this.worldName); + } + + public int getSizeX() { + return this.x2 - this.x1 + 1; + } + + public int getSizeY() { + return this.y2 - this.y1 + 1; + } + + public int getSizeZ() { + return this.z2 - this.z1 + 1; + } + + public Location[] getCornerLocations() { + Location[] result = new Location[8]; + Block[] cornerBlocks = this.getCornerBlocks(); + for (int i = 0; i < cornerBlocks.length; ++i) { + result[i] = cornerBlocks[i].getLocation(); + } + + return result; + } + + public Block[] getCornerBlocks() { + Block[] result = new Block[8]; + World world = this.getWorld(); + result[0] = world.getBlockAt(this.x1, this.y1, this.z1); + result[1] = world.getBlockAt(this.x1, this.y1, this.z2); + result[2] = world.getBlockAt(this.x1, this.y2, this.z1); + result[3] = world.getBlockAt(this.x1, this.y2, this.z2); + result[4] = world.getBlockAt(this.x2, this.y1, this.z1); + result[5] = world.getBlockAt(this.x2, this.y1, this.z2); + result[6] = world.getBlockAt(this.x2, this.y2, this.z1); + result[7] = world.getBlockAt(this.x2, this.y2, this.z2); + + return result; + } + + public Cuboid shift(CuboidDirection direction, int amount) throws IllegalArgumentException { + return this.expand(direction, amount).expand(direction.opposite(), -amount); + } + + public Cuboid inset(CuboidDirection direction, int amount) throws IllegalArgumentException { + return this.outset(direction, -amount); + } + + public Cuboid expand(CuboidDirection direction, int amount) throws IllegalArgumentException { + switch (direction) { + case NORTH: { + return new Cuboid(this.worldName, this.x1 - amount, this.y1, this.z1, this.x2, this.y2, this.z2); + } + case SOUTH: { + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2 + amount, this.y2, this.z2); + } + case EAST: { + return new Cuboid(this.worldName, this.x1, this.y1, this.z1 - amount, this.x2, this.y2, this.z2); + } + case WEST: { + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, this.z2 + amount); + } + case DOWN: { + return new Cuboid(this.worldName, this.x1, this.y1 - amount, this.z1, this.x2, this.y2, this.z2); + } + case UP: { + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2 + amount, this.z2); + } + } + throw new IllegalArgumentException("Invalid direction " + direction); + } + + public Cuboid outset(CuboidDirection direction, int amount) throws IllegalArgumentException { + switch (direction) { + case HORIZONTAL: { + return this.expand(CuboidDirection.NORTH, amount).expand(CuboidDirection.SOUTH, amount).expand(CuboidDirection.EAST, amount).expand(CuboidDirection.WEST, amount); + } + case VERTICAL: { + return this.expand(CuboidDirection.DOWN, amount).expand(CuboidDirection.UP, amount); + } + case BOTH: { + return this.outset(CuboidDirection.HORIZONTAL, amount).outset(CuboidDirection.VERTICAL, amount); + } + } + throw new IllegalArgumentException("Invalid direction " + direction); + } + + public boolean contains(Cuboid cuboid) { + return this.contains(cuboid.getMinimumPoint()) || this.contains(cuboid.getMaximumPoint()); + } + + public boolean contains(Player player) { + return this.contains(player.getLocation()); + } + + public boolean contains(World world, int x, int z) { + return (world == null || this.getWorld().equals(world)) && x >= this.x1 && x <= this.x2 && z >= this.z1 && z <= this.z2; + } + + public boolean contains(int x, int y, int z) { + return x >= this.x1 && x <= this.x2 && y >= this.y1 && y <= this.y2 && z >= this.z1 && z <= this.z2; + } + + public boolean contains(Block block) { + return this.contains(block.getLocation()); + } + + public boolean contains(Location location) { + if (location == null || this.worldName == null) { + return false; + } + World world = location.getWorld(); + + return world != null && this.worldName.equals(location.getWorld().getName()) && this.contains(location.getBlockX(), location.getBlockY(), location.getBlockZ()); + } + + public int getVolume() { + return this.getSizeX() * this.getSizeY() * this.getSizeZ(); + } + + public int getArea() { + Location min = this.getMinimumPoint(); + Location max = this.getMaximumPoint(); + + return (max.getBlockX() - min.getBlockX() + 1) * (max.getBlockZ() - min.getBlockZ() + 1); + } + + public byte getAverageLightLevel() { + long total = 0L; + int count = 0; + for (Block block : this) { + if (!block.isEmpty()) continue; + total += block.getLightLevel(); + ++count; + } + + return count > 0 ? (byte) (total / (long) count) : (byte) 0; + } + + public Location getMinimumPoint() { + return new Location(this.getWorld(), Math.min(this.x1, this.x2), Math.min(this.y1, this.y2), Math.min(this.z1, this.z2)); + } + + public Location getMaximumPoint() { + return new Location(this.getWorld(), Math.max(this.x1, this.x2), Math.max(this.y1, this.y2), Math.max(this.z1, this.z2)); + } + + public int getWidth() { + return this.getMaximumPoint().getBlockX() - this.getMinimumPoint().getBlockX(); + } + + public int getHeight() { + return this.getMaximumPoint().getBlockY() - this.getMinimumPoint().getBlockY(); + } + + public int getLength() { + return this.getMaximumPoint().getBlockZ() - this.getMinimumPoint().getBlockZ(); + } + + public Cuboid contract() { + return this.contract(CuboidDirection.DOWN).contract(CuboidDirection.SOUTH).contract(CuboidDirection.EAST).contract(CuboidDirection.UP).contract(CuboidDirection.NORTH).contract(CuboidDirection.WEST); + } + + public Cuboid contract(CuboidDirection direction) { + Cuboid face = this.getFace(direction.opposite()); + switch (direction) { + case DOWN: { + while (face.containsOnly(Material.AIR) && face.y1 > this.y1) { + face = face.shift(CuboidDirection.DOWN, 1); + } + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, face.y2, this.z2); + } + case UP: { + while (face.containsOnly(Material.AIR) && face.y2 < this.y2) { + face = face.shift(CuboidDirection.UP, 1); + } + return new Cuboid(this.worldName, this.x1, face.y1, this.z1, this.x2, this.y2, this.z2); + } + case NORTH: { + while (face.containsOnly(Material.AIR) && face.x1 > this.x1) { + face = face.shift(CuboidDirection.NORTH, 1); + } + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, face.x2, this.y2, this.z2); + } + case SOUTH: { + while (face.containsOnly(Material.AIR) && face.x2 < this.x2) { + face = face.shift(CuboidDirection.SOUTH, 1); + } + return new Cuboid(this.worldName, face.x1, this.y1, this.z1, this.x2, this.y2, this.z2); + } + case EAST: { + while (face.containsOnly(Material.AIR) && face.z1 > this.z1) { + face = face.shift(CuboidDirection.EAST, 1); + } + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, face.z2); + } + case WEST: { + while (face.containsOnly(Material.AIR) && face.z2 < this.z2) { + face = face.shift(CuboidDirection.WEST, 1); + } + return new Cuboid(this.worldName, this.x1, this.y1, face.z1, this.x2, this.y2, this.z2); + } + } + throw new IllegalArgumentException("Invalid direction " + direction); + } + + public Cuboid getFace(CuboidDirection direction) { + switch (direction) { + case DOWN: { + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y1, this.z2); + } + case UP: { + return new Cuboid(this.worldName, this.x1, this.y2, this.z1, this.x2, this.y2, this.z2); + } + case NORTH: { + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x1, this.y2, this.z2); + } + case SOUTH: { + return new Cuboid(this.worldName, this.x2, this.y1, this.z1, this.x2, this.y2, this.z2); + } + case EAST: { + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, this.z1); + } + case WEST: { + return new Cuboid(this.worldName, this.x1, this.y1, this.z2, this.x2, this.y2, this.z2); + } + } + throw new IllegalArgumentException("Invalid direction " + direction); + } + + public boolean containsOnly(Material material) { + for (Block block : this) { + if (block.getType() == material) continue; + return false; + } + + return true; + } + + public Cuboid getBoundingCuboid(Cuboid other) { + if (other == null) { + return this; + } + int xMin = Math.min(this.x1, other.x1); + int yMin = Math.min(this.y1, other.y1); + int zMin = Math.min(this.z1, other.z1); + int xMax = Math.max(this.x2, other.x2); + int yMax = Math.max(this.y2, other.y2); + int zMax = Math.max(this.z2, other.z2); + + return new Cuboid(this.worldName, xMin, yMin, zMin, xMax, yMax, zMax); + } + + public Block getRelativeBlock(int x, int y, int z) { + return this.getWorld().getBlockAt(this.x1 + x, this.y1 + y, this.z1 + z); + } + + public Block getRelativeBlock(World world, int x, int y, int z) { + return world.getBlockAt(this.x1 + x, this.y1 + y, this.z1 + z); + } + + public List getChunks() { + World world = this.getWorld(); + int x1 = this.x1 & -16; + int x2 = this.x2 & -16; + int z1 = this.z1 & -16; + int z2 = this.z2 & -16; + + ArrayList result = new ArrayList<>(x2 - x1 + 16 + (z2 - z1) * 16); + for (int x3 = x1; x3 <= x2; x3 += 16) { + for (int z3 = z1; z3 <= z2; z3 += 16) { + result.add(world.getChunkAt(x3 >> 4, z3 >> 4)); + } + } + + return result; + } + + @Override + public Iterator iterator() { + return new CuboidBlockIterator(this.getWorld(), this.x1, this.y1, this.z1, this.x2, this.y2, this.z2); + } + + public Iterator locationIterator() { + return new CuboidLocationIterator(this.getWorld(), this.x1, this.y1, this.z1, this.x2, this.y2, this.z2); + } + + public Cuboid clone() { + try { + return (Cuboid) super.clone(); + } catch (CloneNotSupportedException ex) { + throw new RuntimeException("This could never happen", ex); + } + } + + public String toString() { + return "Cuboid: " + this.worldName + ',' + this.x1 + ',' + this.y1 + ',' + this.z1 + "=>" + this.x2 + ',' + this.y2 + ',' + this.z2; + } + + public String getWorldName() { + return this.worldName; + } + + public int getX1() { + return this.x1; + } + + public int getY1() { + return this.y1; + } + + public int getZ1() { + return this.z1; + } + + public int getX2() { + return this.x2; + } + + public int getY2() { + return this.y2; + } + + public int getZ2() { + return this.z2; + } + + public void setWorldName(String worldName) { + this.worldName = worldName; + } + + public void setX1(int x1) { + this.x1 = x1; + } + + public void setY1(int y1) { + this.y1 = y1; + } + + public void setZ1(int z1) { + this.z1 = z1; + } + + public void setX2(int x2) { + this.x2 = x2; + } + + public void setY2(int y2) { + this.y2 = y2; + } + + public void setZ2(int z2) { + this.z2 = z2; + } +} + diff --git a/src/main/java/rip/tilly/bedwars/utils/cuboid/CuboidBlockIterator.java b/src/main/java/rip/tilly/bedwars/utils/cuboid/CuboidBlockIterator.java new file mode 100644 index 0000000..5db95bd --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/utils/cuboid/CuboidBlockIterator.java @@ -0,0 +1,97 @@ +package rip.tilly.bedwars.utils.cuboid; + +import org.bukkit.World; +import org.bukkit.block.Block; + +import java.util.Iterator; + +public class CuboidBlockIterator implements Iterator { + + private World world; + private int baseX; + private int baseY; + private int baseZ; + private int sizeX; + private int sizeY; + private int sizeZ; + private int x; + private int y; + private int z; + + CuboidBlockIterator(World world, int x1, int y1, int z1, int x2, int y2, int z2) { + this.world = world; + this.baseX = x1; + this.baseY = y1; + this.baseZ = z1; + this.sizeX = Math.abs(x2 - x1) + 1; + this.sizeY = Math.abs(y2 - y1) + 1; + this.sizeZ = Math.abs(z2 - z1) + 1; + this.z = 0; + this.y = 0; + this.x = 0; + } + + @Override + public boolean hasNext() { + return this.x < this.sizeX && this.y < this.sizeY && this.z < this.sizeZ; + } + + @Override + public Block next() { + Block block = this.world.getBlockAt(this.baseX + this.x, this.baseY + this.y, this.baseZ + this.z); + if (++this.x >= this.sizeX) { + this.x = 0; + if (++this.y >= this.sizeY) { + this.y = 0; + ++this.z; + } + } + return block; + } + + @Override + public void remove() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + public World getWorld() { + return this.world; + } + + public int getBaseX() { + return this.baseX; + } + + public int getBaseY() { + return this.baseY; + } + + public int getBaseZ() { + return this.baseZ; + } + + public int getSizeX() { + return this.sizeX; + } + + public int getSizeY() { + return this.sizeY; + } + + public int getSizeZ() { + return this.sizeZ; + } + + public int getX() { + return this.x; + } + + public int getY() { + return this.y; + } + + public int getZ() { + return this.z; + } +} + diff --git a/src/main/java/rip/tilly/bedwars/utils/cuboid/CuboidDirection.java b/src/main/java/rip/tilly/bedwars/utils/cuboid/CuboidDirection.java new file mode 100644 index 0000000..e99ac6f --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/utils/cuboid/CuboidDirection.java @@ -0,0 +1,46 @@ +package rip.tilly.bedwars.utils.cuboid; + +public enum CuboidDirection { + + NORTH, EAST, SOUTH, WEST, + UP, DOWN, HORIZONTAL, VERTICAL, BOTH, + UNKNOWN; + + private CuboidDirection() { + + } + + public CuboidDirection opposite() { + switch (this) { + case NORTH: { + return SOUTH; + } + case EAST: { + return WEST; + } + case SOUTH: { + return NORTH; + } + case WEST: { + return EAST; + } + case HORIZONTAL: { + return VERTICAL; + } + case VERTICAL: { + return HORIZONTAL; + } + case UP: { + return DOWN; + } + case DOWN: { + return UP; + } + case BOTH: { + return BOTH; + } + } + return UNKNOWN; + } +} + diff --git a/src/main/java/rip/tilly/bedwars/utils/cuboid/CuboidLocationIterator.java b/src/main/java/rip/tilly/bedwars/utils/cuboid/CuboidLocationIterator.java new file mode 100644 index 0000000..33aed75 --- /dev/null +++ b/src/main/java/rip/tilly/bedwars/utils/cuboid/CuboidLocationIterator.java @@ -0,0 +1,97 @@ +package rip.tilly.bedwars.utils.cuboid; + +import org.bukkit.Location; +import org.bukkit.World; + +import java.util.Iterator; + +public class CuboidLocationIterator implements Iterator { + + private World world; + private int baseX; + private int baseY; + private int baseZ; + private int sizeX; + private int sizeY; + private int sizeZ; + private int x; + private int y; + private int z; + + CuboidLocationIterator(World world, int x1, int y1, int z1, int x2, int y2, int z2) { + this.world = world; + this.baseX = x1; + this.baseY = y1; + this.baseZ = z1; + this.sizeX = Math.abs(x2 - x1) + 1; + this.sizeY = Math.abs(y2 - y1) + 1; + this.sizeZ = Math.abs(z2 - z1) + 1; + this.z = 0; + this.y = 0; + this.x = 0; + } + + @Override + public boolean hasNext() { + return this.x < this.sizeX && this.y < this.sizeY && this.z < this.sizeZ; + } + + @Override + public Location next() { + Location location = new Location(this.world, this.baseX + this.x, this.baseY + this.y, this.baseZ + this.z); + if (++this.x >= this.sizeX) { + this.x = 0; + if (++this.y >= this.sizeY) { + this.y = 0; + ++this.z; + } + } + return location; + } + + @Override + public void remove() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + public World getWorld() { + return this.world; + } + + public int getBaseX() { + return this.baseX; + } + + public int getBaseY() { + return this.baseY; + } + + public int getBaseZ() { + return this.baseZ; + } + + public int getSizeX() { + return this.sizeX; + } + + public int getSizeY() { + return this.sizeY; + } + + public int getSizeZ() { + return this.sizeZ; + } + + public int getX() { + return this.x; + } + + public int getY() { + return this.y; + } + + public int getZ() { + return this.z; + } +} +