/*
* This file is part of Libelula Minecraft Edition Project.
*
* Libelula Minecraft Edition is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Libelula Minecraft Edition is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Libelula Minecraft Edition.
* If not, see <http://www.gnu.org/licenses/>.
*
*/
package me.libelula.liderswag;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.locks.ReentrantLock;
import me.confuser.barapi.BarAPI;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Skull;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.potion.PotionEffect;
/**
*
* @author Diego D'Onofrio <ddonofrio@member.fsf.org>
*/
public class GameManager {
private class Game {
long endTime;
}
private final Main plugin;
private final TreeMap<Player, ArenaManager.Arena> players;
private final ReentrantLock _players_Lock;
private final TreeMap<String, HeraldData> spectatorMessages;
private final TreeMap<String, HeraldData> inGameMessages;
private final TreeMap<String, Game> games;
private class HeraldData {
String message;
long time;
public HeraldData(String message, long time) {
this.message = message;
this.time = time;
}
}
public GameManager(final Main plugin) {
this.plugin = plugin;
players = new TreeMap<>(new Tools.PlayerComparator());
_players_Lock = new ReentrantLock(true);
spectatorMessages = new TreeMap<>();
inGameMessages = new TreeMap<>();
for (String arenaName : plugin.am.getList().keySet()) {
ArenaManager.Arena arena = plugin.am.getArena(arenaName);
if (arena.isEnabled()) {
clearHeads(arena);
}
}
games = new TreeMap<>();
checkIntrudersRoutine();
gameRoutine();
}
private void setInventory(Player player, ArenaManager.Arena arena) {
player.getInventory().setContents(arena.getStartingKit());
player.getInventory().setBoots(arena.getBoots());
player.getInventory().setLeggings(arena.getLeggings());
player.getInventory().setChestplate(arena.getChestplate());
player.getInventory().setHelmet(arena.getHelmet());
}
public void addPlayerToGame(Player player, ArenaManager.Arena arena) {
_players_Lock.lock();
try {
arena.removePlayerFromSpectator(player);
plugin.pm.setInGame(player);
teleportPlayerIntoArena(player, arena);
arena.addPlayerToGame(player);
} finally {
_players_Lock.unlock();
}
}
public void turnSpectator(Player player) {
ArenaManager.Arena arena = players.get(player);
if (arena != null) {
arena.removePlayerFromGame(player);
addPlayerToSpectators(player, arena);
}
}
public void removePlayer(Player player) {
_players_Lock.lock();
try {
ArenaManager.Arena arena = players.remove(player);
if (arena != null) {
if (arena.isPlaying(player)) {
arena.removePlayerFromGame(player);
plugin.pm.backToNormal(player);
player.teleport(plugin.lobby);
} else {
removePlayerFromSpectator(player, arena);
}
}
} finally {
_players_Lock.unlock();
}
}
private void removePlayerFromSpectator(Player player, ArenaManager.Arena arena) {
players.remove(player);
arena.removePlayerFromSpectator(player);
plugin.pm.backToNormal(player);
player.teleport(plugin.lobby);
}
public void removeAllPlayers() {
_players_Lock.lock();
try {
for (Player player : players.keySet()) {
ArenaManager.Arena arena = players.get(player);
if (arena != null) {
arena.removePlayerFromSpectator(player);
}
plugin.pm.backToNormal(player);
player.teleport(plugin.lobby);
}
players.clear();
} finally {
_players_Lock.unlock();
}
}
public void addPlayerToSpectators(Player player, ArenaManager.Arena arena) {
if (arena != null) {
if (arena.isEnabled()) {
_players_Lock.lock();
List<Player> overTakenPlayers;
ArenaManager.QueuePriority priority = plugin.pm.getPriority(player);
try {
arena.addPlayerToQueue(player, priority);
players.put(player, arena);
overTakenPlayers = arena.getPlayersBehind(player);
player.teleport(arena.getNextSpawnPoint());
plugin.pm.setSpectator(player);
} finally {
_players_Lock.unlock();
}
String overtakingMessage;
switch (priority) {
case HIGHEST:
overtakingMessage = plugin.lm.getText("overtaken-by-highest");
break;
case HIGH:
overtakingMessage = plugin.lm.getText("overtaken-by-high");
break;
case NORMAL:
overtakingMessage = plugin.lm.getText("overtaken-by-normal");
break;
default:
overtakingMessage = plugin.lm.getText("overtaken-by-low");
break;
}
overtakingMessage = overtakingMessage.replace("%PLAYER%", player.getDisplayName());
for (Player overTaken : overTakenPlayers) {
overTaken.sendMessage(overtakingMessage);
}
} else {
plugin.lm.sendText(player, "arena-is-disabled");
}
} else {
plugin.lm.sendText(player, "arena-does-not-exists");
}
}
public void controlPlayerMovement(PlayerMoveEvent e) {
ArenaManager.Arena arena = players.get(e.getPlayer());
if (arena != null) {
Player player = e.getPlayer();
if (arena.isSpectator(player)) {
if (!arena.isInsideColisseum(e.getTo())) {
if (arena.isInsideColisseum(e.getFrom())) {
e.setCancelled(true);
player.teleport(e.getFrom());
if (!player.isFlying() && e.getTo().getY() < e.getFrom().getY()) {
player.setFlying(true);
}
} else {
player.teleport(arena.getNextSpawnPoint());
}
plugin.lm.sendText(player, "spectator-cant-exit");
} else if (arena.isInsideArena(e.getTo())) {
if (!arena.isInsideArena(e.getFrom())) {
e.setCancelled(true);
player.teleport(e.getFrom());
if (!player.isFlying() && e.getTo().getY() < e.getFrom().getY()) {
player.setFlying(true);
}
} else {
player.teleport(arena.getNextSpawnPoint());
}
plugin.lm.sendText(player, "spectator-cant-getin-arena");
}
} else if (arena.isPlaying(player)) {
if (!arena.isInsideArena(e.getTo())) {
e.setCancelled(true);
if (arena.isInsideArena(e.getFrom())) {
player.teleport(e.getFrom());
} else {
teleportPlayerIntoArena(player, arena);
}
plugin.lm.sendText(player, "player-outside-arena");
}
}
}
}
public boolean isPlayerInArena(Player player) {
return players.containsKey(player);
}
private void checkIntrudersRoutine() {
Bukkit.getScheduler().runTaskTimer(plugin, new Runnable() {
@Override
public void run() {
final TreeMap<Location, Player> playerLocations = new TreeMap<>(new Tools.LocationBlockComparator());
for (Player player : plugin.getServer().getOnlinePlayers()) {
playerLocations.put(player.getLocation(), player);
}
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
@Override
public void run() {
for (String arenaName : plugin.am.getList().keySet()) {
final ArenaManager.Arena arena = plugin.am.getArena(arenaName);
if (arena.isEnabled()) {
for (Location loc : playerLocations.keySet()) {
final Player player = playerLocations.get(loc);
if (arena.isInsideColisseum(loc) && !arena.hasPlayer(player)) {
Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
if (!player.hasPermission("lls.intruder")) {
player.teleport(plugin.lobby);
}
}
;
}
);
}
} }
}
}
;});
}
;}, 30, 30);
}
private void herald(PlayerManager.PlayerGroup group, String message, ArenaManager.Arena arena) {
HeraldData hd;
if (group == PlayerManager.PlayerGroup.SPECTATOR) {
hd = spectatorMessages.get(arena.getName());
} else {
hd = inGameMessages.get(arena.getName());
}
if (hd != null && hd.message.equals(message)) {
long now = new Date().getTime();
if (now < hd.time + 10000) {
return;
}
}
hd = new HeraldData(message, new Date().getTime());
if (group == PlayerManager.PlayerGroup.SPECTATOR) {
spectatorMessages.put(arena.getName(), hd);
for (Player player : arena.getSpectators()) {
player.sendMessage(message);
}
} else {
inGameMessages.put(arena.getName(), hd);
for (Player player : arena.getInGamePlayers()) {
player.sendMessage(message);
}
}
}
public void teleportPlayerIntoArena(Player player, ArenaManager.Arena arena) {
TreeSet<Player> inGamePlayers = arena.getInGamePlayers();
if (inGamePlayers.isEmpty()) {
player.teleport(arena.getP1StartPoint());
} else {
Player inGame = arena.getInGamePlayers().iterator().next();
if (inGame.getLocation().distance(arena.getP1StartPoint())
< inGame.getLocation().distance(arena.getP2StartPoint())) {
player.teleport(arena.getP2StartPoint());
} else {
player.teleport(arena.getP1StartPoint());
}
}
}
private void gameRoutine() {
Bukkit.getScheduler().runTaskTimer(plugin, new Runnable() {
@Override
public void run() {
for (String arenaName : plugin.am.getList().keySet()) {
ArenaManager.Arena arena = plugin.am.getArena(arenaName);
if (!arena.isEnabled()) {
continue;
}
Game game = games.get(arenaName);
TreeSet<Player> inGame = arena.getInGamePlayers();
if (inGame.size() == 2) {
if (game != null && game.endTime > 0) {
if (new Date().getTime() > game.endTime) {
List<Player> players = new ArrayList<>();
players.addAll(arena.getInGamePlayers());
for (Player player : players) {
turnSpectator(player);
}
herald(PlayerManager.PlayerGroup.SPECTATOR, plugin.lm.getText("time-out"), arena);
game.endTime = -1;
}
}
continue;
}
if (arena.getSpectatorCount() + arena.getinGameCount() < 2) {
herald(PlayerManager.PlayerGroup.SPECTATOR, plugin.lm.getText("waiting-for-players"), arena);
} else {
while (arena.getinGameCount() < 2 && arena.getSpectatorCount() >= 1) {
Player nextPlayer = arena.removeFirstInQueue();
addPlayerToGame(nextPlayer, arena);
nextPlayer.sendMessage(plugin.lm.getText("fight"));
if (arena.getinGameCount() == 2) {
gameStart(arena);
}
}
}
}
}
;}, 20, 20);
}
public void gameOver(Player looser) {
final ArenaManager.Arena arena = players.get(looser);
TreeMap<String, String> dict = new TreeMap<>();
dict.put("%PLAYER%", looser.getDisplayName());
herald(PlayerManager.PlayerGroup.SPECTATOR, plugin.lm.getText("lider-defeated", dict), arena);
clearHeads(arena);
if (arena != null) {
arena.incInGameDummyPlayerCounter();
turnSpectator(looser);
TreeSet<Player> inGamePlayers = arena.getInGamePlayers();
if (inGamePlayers.isEmpty()) {
herald(PlayerManager.PlayerGroup.SPECTATOR, plugin.lm.getText("game-draw"), arena);
} else {
final Player winner = arena.getInGamePlayers().iterator().next();
dict.put("%PLAYER%", winner.getDisplayName());
herald(PlayerManager.PlayerGroup.SPECTATOR, plugin.lm.getText("player-win-game", dict), arena);
winner.setFireTicks(0);
for (PotionEffect effect : winner.getActivePotionEffects()) {
winner.removePotionEffect(effect.getType());
}
plugin.sm.playReminigHealthPointsEffect(winner);
Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
@Override
public void run() {
arena.clearDummyPlayerCounter();
plugin.pm.setInGame(winner);
}
;}, 20 * 8);
}
}
}
public void teleportToSpectator(Player player) {
ArenaManager.Arena arena = players.get(player);
if (arena != null) {
player.teleport(arena.getNextSpawnPoint());
}
}
public void gameStart(ArenaManager.Arena arena) {
arena.sweep();
for (Player player : arena.getInGamePlayers()) {
plugin.pm.setGameMode(player);
setInventory(player, arena);
BarAPI.setMessage(player, plugin.lm.getText("time-left", false), 120);
}
final List<Player> queue = arena.getPossitions();
for (Player player : arena.getSpectators()) {
BarAPI.setMessage(player, plugin.lm.getText("time-left", false), 120);
}
Game game = new Game();
game.endTime = new Date().getTime() + 120 * 1000;
games.put(arena.getName(), game);
Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
@Override
public void run() {
int i = 0;
for (Player player : queue) {
if (i == 0) {
plugin.lm.sendText(player, "you-are-next");
} else if (i == 1) {
player.sendMessage(plugin.lm.getText("possition-left").replace("%POSITION%", "" + i));
} else {
player.sendMessage(plugin.lm.getText("possitions-left").replace("%POSITION%", "" + i));
}
i++;
}
}
;}, 20);
}
public final void clearHeads(ArenaManager.Arena arena) {
TreeMap<Integer, Skull> skulls = arena.getScoreHeads();
if (skulls != null) {
for (Skull skull : skulls.values()) {
skull.getBlock().setType(Material.AIR);
}
}
}
}